diff --git a/1.html b/1.html new file mode 100644 index 0000000..e09fc0e --- /dev/null +++ b/1.html @@ -0,0 +1,283 @@ + + + + + + 温暖存折 - 我的微长征 + + + +
+ +
+

温暖存折

+
我的“微长征”21天温暖行动
+
+

姓  名 _________________

+

班  级 _________________

+

行动时间 2026年__月__日 至 __月__日

+

温暖目标 存满 ______ 次温暖

+
+
❤️ 温暖行动 ❤️
+
+

存折号:WE⁰⁰⁰¹

+

签发:“微长征”中队

+
+
+ + +
+

📖 温暖存款记录

+ + + + + + + + + +
日期我做了什么对方反应/我的感受见证人
__月 __日
__月 __日
__月 __日
+
+

✨ 我的第一份温暖:_________________________

+

💬 蔡威叔叔说“为了明天”,我今天做了:

+
+
第1周 · 小红军签名 ___________
+
+
+ + +
+ +
+

📖 温暖存款记录(续)

+ + + + + + + +
日期我做了什么对方反应/我的感受见证人
__月 __日
__月 __日
__月 __日
+
+

🏅 我获得的第一枚勋章日期:__________ 因为我帮助了____________

+

❤️ 我的成长发现:

+
+
第2周 · 小红军签名 ___________
+
+ + +
+

⭐ 微长征勋章 ⭐

+
+ 🏅 🏅 🏅
+ (每积累3笔温暖,请老师/伙伴盖一枚红章) +
+
+

🌟 21天后,我最想对自己说:

+

+

🌟 我想对蔡威叔叔说:

+

+
+
+ “英雄不是做惊天动地的事,
+ 而是在别人最需要的时候,选择不转身离开。” +
+
温暖见证人:__________ 家长/老师
+
+
+ + + \ No newline at end of file diff --git a/2.html b/2.html new file mode 100644 index 0000000..7e24d57 --- /dev/null +++ b/2.html @@ -0,0 +1,246 @@ + + + + + + 温暖存折 - 我的微长征 + + + + + + +
+ +
+

📖 温暖存款记录(续)

+ + + + + + + +
日期我做了什么对方反应/我的感受见证人
__月 __日
__月 __日
__月 __日
+
+

🏅 我获得的第一枚勋章日期:__________ 因为我帮助了____________

+

❤️ 我的成长发现:

+
+
第2周 · 小红军签名 ___________
+
+ + +
+

⭐ 微长征勋章 ⭐

+
+ 🏅 🏅 🏅
+ (每积累3笔温暖,请老师/伙伴盖一枚红章) +
+
+

🌟 21天后,我最想对自己说:

+

+

🌟 我想对蔡威叔叔说:

+

+
+
+ “英雄不是做惊天动地的事,
+ 而是在别人最需要的时候,选择不转身离开。” +
+
温暖见证人:__________ 家长/老师
+
+
+ + + \ No newline at end of file diff --git a/CPython/c.py b/CPython/c.py deleted file mode 100644 index 3370618..0000000 --- a/CPython/c.py +++ /dev/null @@ -1,690 +0,0 @@ -# C语法定义模块 - -import ast -import sys -import os -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) - -from . import t - -def _to_str(node): - if node is None: - return '' - if isinstance(node, str): - return node - if isinstance(node, list): - return ' && '.join([_to_str(n) for n in node]) - NodeType = type(node).__name__ - if NodeType == 'Constant': - return node.value - elif NodeType == 'ID': - return node.name - elif NodeType == 'BinaryOp': - left = _to_str(node.left) - right = _to_str(node.right) - return f'{left} {node.op} {right}' - elif NodeType == 'UnaryOp': - expr = _to_str(node.expr) - return f'{node.op}{expr}' - else: - return repr(node) - -class Asm: - @staticmethod - def HandleCall(translator, args, keywords): - if not args: - return ['__asm__ volatile ("nop");'] - - # ========== 核心变量 ========== - output_ops = [] # (值表达式, 约束符) - input_ops = [] # (值表达式, 约束符) - clobbers = [] # 破坏列表实际值 - operand_seq = 0 # 占位符编号 - - # ========== 核心修复:递归提取ASM_DESCR值(支持|组合) ========== - def parse_asm_descr(expr): - """ - 递归解析AST节点,确保获取t.ASM_DESCR的实际值,支持|组合 - 处理场景: - 1. t.ASM_DESCR.XXX → 取属性值 - 2. t.ASM_DESCR.XXX | t.ASM_DESCR.YYY → 拼接两个值 - 3. 常量字符串 → 直接返回 - """ - # 场景1:位或组合(XXX | YYY) - if isinstance(expr, ast.BinOp): - left_val = parse_asm_descr(expr.left) - right_val = parse_asm_descr(expr.right) - return left_val + right_val - - # 场景2:t.ASM_DESCR.XXX 多层属性访问 - elif isinstance(expr, ast.Attribute): - # 第一步:判断是否是 t.ASM_DESCR 的属性 - if isinstance(expr.value, ast.Attribute): - # 内层是 t.ASM_DESCR - if (isinstance(expr.value.value, ast.Name) and - expr.value.value.id == 't' and - expr.value.attr == 'ASM_DESCR'): - # 取 t.ASM_DESCR.XXX 的实际值 - AttrName = expr.attr - if hasattr(t.ASM_DESCR, AttrName): - return getattr(t.ASM_DESCR, AttrName, "") - - # 兼容 t.XXX 简化写法(如果有的话) - elif isinstance(expr.value, ast.Name) and expr.value.id == 't': - AttrName = expr.attr - if hasattr(t.ASM_DESCR, AttrName): - return getattr(t.ASM_DESCR, AttrName, "") - - # 场景3:直接传常量(如 "r"、"cc") - elif isinstance(expr, ast.Constant): - return expr.value - - # 其他场景返回空 - return "" - - # ========== 步骤1:处理f-string中的内联AsmInp/AsmOut ========== - asm_code = "" - first_arg = args[0] - - if isinstance(first_arg, ast.JoinedStr): - asm_parts = [] - for part in first_arg.values: - if isinstance(part, ast.Constant): - asm_parts.append(part.value) - elif isinstance(part, ast.FormattedValue): - expr = part.value - if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute) and expr.func.value.id == 'c': - # 解析内联的AsmInp/AsmOut - call_node = expr - val_ExprNode = translator.HandleExpr(call_node.args[0])[0] if len(call_node.args)>=1 else "" - if isinstance(val_ExprNode, str): - val_expr = val_ExprNode - else: - try: - val_expr = str(val_ExprNode) - except: - val_expr = '' - constraint = parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" - - if call_node.func.attr == 'AsmOut': - output_ops.append((val_expr, constraint)) - asm_parts.append(f"%{operand_seq}") - operand_seq += 1 - elif call_node.func.attr == 'AsmInp': - input_ops.append((val_expr, constraint)) - asm_parts.append(f"%{operand_seq}") - operand_seq += 1 - else: - asm_parts.append(translator.HandleExpr(expr)[0]) - asm_code = ''.join(asm_parts) - elif isinstance(first_arg, ast.Constant): - asm_code = first_arg.value - - # ========== 步骤2:处理参数中的AsmInp/AsmOut和破坏列表 ========== - def parse_operand(arg): - """解析 AsmInp/AsmOut 参数""" - if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute) and arg.func.value.id == 'c': - call_node = arg - val_ExprNode = translator.HandleExpr(call_node.args[0])[0] if len(call_node.args)>=1 else "" - if isinstance(val_ExprNode, str): - val_expr = val_ExprNode - else: - try: - val_expr = str(val_ExprNode) - except: - val_expr = '' - constraint = parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" - - if call_node.func.attr == 'AsmOut': - return ('out', val_expr, constraint) - elif call_node.func.attr == 'AsmInp': - return ('in', val_expr, constraint) - return None - - for arg in args[1:]: - result = parse_operand(arg) - if result: - direction, val_expr, constraint = result - if direction == 'out': - output_ops.append((val_expr, constraint)) - operand_seq += 1 - elif direction == 'in': - input_ops.append((val_expr, constraint)) - operand_seq += 1 - elif isinstance(arg, ast.List): - # 解析破坏列表(支持|组合) - for elt in arg.elts: - clobber_val = parse_asm_descr(elt) - if clobber_val: - clobbers.append(clobber_val) - - # ========== 步骤2.5:处理关键字参数 out 和 op ========== - for kw in keywords: - if kw.arg == 'out': - # 处理 out 关键字参数 (输出操作数) - if isinstance(kw.value, ast.List): - for elt in kw.value.elts: - result = parse_operand(elt) - if result and result[0] == 'out': - output_ops.append((result[1], result[2])) - operand_seq += 1 - elif isinstance(kw.value, ast.Call): - result = parse_operand(kw.value) - if result and result[0] == 'out': - output_ops.append((result[1], result[2])) - operand_seq += 1 - elif kw.arg == 'op': - # 处理 op 关键字参数 (clobber,破坏列表) - if isinstance(kw.value, ast.List): - for elt in kw.value.elts: - clobber_val = parse_asm_descr(elt) - if clobber_val: - clobbers.append(clobber_val) - elif kw.arg == 'inp' or kw.arg == 'inputs': - # 处理 inp/inputs 关键字参数 (输入操作数,追加到f-string中已有输入之后) - if isinstance(kw.value, ast.List): - for elt in kw.value.elts: - if isinstance(elt, ast.Tuple): - # 处理列表中的 (value, constraint) 元组格式 - if len(elt.elts) >= 2: - val_ExprNode = translator.HandleExpr(elt.elts[0])[0] if len(elt.elts) >= 1 else "" - if isinstance(val_ExprNode, str): - val_expr = val_ExprNode - else: - try: - val_expr = str(val_ExprNode) - except: - val_expr = '' - constraint = parse_asm_descr(elt.elts[1]) - input_ops.append((val_expr, constraint)) - operand_seq += 1 - else: - result = parse_operand(elt) - if result and result[0] == 'in': - input_ops.append((result[1], result[2])) - operand_seq += 1 - elif isinstance(kw.value, ast.Call): - result = parse_operand(kw.value) - if result and result[0] == 'in': - input_ops.append((result[1], result[2])) - operand_seq += 1 - elif isinstance(kw.value, ast.Tuple): - # 处理 (value, constraint) 元组格式 - if len(kw.value.elts) >= 2: - val_ExprNode = translator.HandleExpr(kw.value.elts[0])[0] if len(kw.value.elts) >= 1 else "" - if isinstance(val_ExprNode, str): - val_expr = val_ExprNode - else: - try: - val_expr = str(val_ExprNode) - except: - val_expr = '' - constraint = parse_asm_descr(kw.value.elts[1]) - input_ops.append((val_expr, constraint)) - operand_seq += 1 - elif kw.arg == 'clobber': - # 处理 clobber 关键字参数 - if isinstance(kw.value, ast.List): - for elt in kw.value.elts: - clobber_val = parse_asm_descr(elt) - if clobber_val: - clobbers.append(clobber_val) - - # ========== 步骤3:格式化汇编代码 ========== - asm_lines = [line.strip() for line in asm_code.split('\n') if line.strip()] - formatted_asm = '\n '.join([f'"{line}\\n"' for line in asm_lines]) - - # ========== 步骤4:拼接约束字符串 ========== - # 输出约束:如果约束已包含 = 或 +,直接使用;否则添加 = - def format_constraint(constraint, is_output=True): - if not constraint: - return "" - # 如果约束已包含修饰符,直接返回 - if '=' in constraint or '+' in constraint: - return constraint - # 否则添加适当的修饰符 - return ('=' if is_output else '') + constraint - - out_const = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else "" - in_const = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else "" - clobber_const = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else "" - - # 构建约束部分:确保冒号格式正确 - constraint_parts = [] - # 输出约束 - if output_ops: - constraint_parts.append(f': {out_const}') - elif input_ops or clobbers: - constraint_parts.append(':') - - # 输入约束 - if input_ops: - constraint_parts.append(f': {in_const}') - elif clobbers: - constraint_parts.append(':') - - # 破坏列表 - if clobbers: - constraint_parts.append(f': {clobber_const}') - - constraint_str = ' '.join(constraint_parts) - - # ========== 生成最终代码 ========== - final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' - return [final_asm] - -class AsmInp: - def __init__(self, value, constraint): - self.value = value - self.constraint = constraint - @staticmethod - def HandleCall(translator, args, keywords): - return [] - -class AsmOut: - def __init__(self, value, constraint): - self.value = value - self.constraint = constraint - @staticmethod - def HandleCall(translator, args, keywords): - return [] - -class NoBreak: - """ switch 分支无break """ - pass - -class Break: - """ switch 分支提前break """ - pass - -class Load: - """解引用a写入b,等价于 *b = *a,无拷贝副作用""" - def __init__(self, src, dst): - self.src = src - self.dst = dst - - @staticmethod - def HandleCall(translator, args, keywords): - if len(args) >= 2: - src = translator.HandleExpr(args[0])[0] - dst = translator.HandleExpr(args[1])[0] - return [f'*({dst}) = *({src})'] - return [] - - -class Addr: - """取地址""" - def __init__(self, addr): - self.addr = addr - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.Addr() 调用""" - if args: - expr = translator.HandleExpr(args[0])[0] - if isinstance(expr, str): - return [f'&{expr}'] - return [f'&{_to_str(expr)}'] - return ['0'] - - -class Deref: - """解引用""" - def __init__(self, ptr): - self.ptr = ptr - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.Deref() 调用""" - if args: - expr = translator.HandleExpr(args[0])[0] - if hasattr(expr, 'op') and expr.op == '*': - return [expr] - return [f'*({_to_str(expr)})'] - return ['0'] - - -class DerefAs: - """解引用写入,等价于 *ptr = value""" - def __init__(self, ptr, value): - self.ptr = ptr - self.value = value - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.DerefAs() 调用""" - if len(args) >= 2: - ptr = translator.HandleExpr(args[0])[0] - val = translator.HandleExpr(args[1])[0] - return [f'*({_to_str(ptr)}) = {_to_str(val)}'] - return [] - - -class Set: - """设置值""" - def __init__(self, key, value): - self.key = key - self.value = value - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.Set() 调用""" - if len(args) >= 2: - target = translator.HandleExpr(args[0])[0] - value = translator.HandleExpr(args[1])[0] - return [f'{_to_str(target)} = {_to_str(value)}'] - return [] - - -class CReturn: - """多返回值装饰器 - - 用于实现函数多返回值,通过匿名结构体返回实现。 - 例如:@c.CReturn(t.CInt, t.CInt) 表示函数返回两个 int 值。 - 等价于 -> tuple[t.CInt, t.CInt] 返回类型注解。 - - 规则: - 1. CReturn 中有几个类型就说明要返回几个值 - 2. 函数返回类型为匿名结构体 { type1, type2, ... } - 3. return 语句使用 insert_value 构建结构体 - 4. 调用处使用 extract_value 提取各字段 - """ - def __init__(self, *ReturnTypes): - self.ReturnTypes = ReturnTypes - - def __call__(self, func): - """装饰器调用""" - # 将返回类型信息附加到函数上 - func._CreturnTypes = self.ReturnTypes - return func - - -class CDefine: - """#define 宏定义""" - def __init__(self, name, value): - self.name = name - self.value = value - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CDefine() 调用""" - if len(args) >= 1: - if isinstance(args[0], ast.Constant): - name = args[0].value - else: - name = 'MACRO' - if len(args) >= 2: - value = translator.HandleExpr(args[1])[0] - return ['#define ' + str(name) + ' ' + _to_str(value)] - return ['#define ' + str(name)] - return [] - - -class CIfndef: - """#ifndef 条件编译""" - def __init__(self, condition): - self.condition = condition - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CIfndef() 调用""" - if args: - condition = translator.HandleExpr(args[0])[0] - return ['#ifndef ' + _to_str(condition)] - return ['#if 0'] - -class CIfdef: - """#ifdef 条件编译""" - def __init__(self, condition): - self.condition = condition - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CIfdef() 调用""" - if args: - condition = translator.HandleExpr(args[0])[0] - return ['#ifdef ' + _to_str(condition)] - return ['#if 0'] - -class CError: - """#error 错误信息""" - def __init__(self, condition): - self.condition = condition - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CError() 调用""" - if args: - # 如果是字符串常量,保留引号 - if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str): - return ['#error "' + args[0].value + '"'] - elif isinstance(args[0], ast.Str): - return ['#error "' + args[0].s + '"'] - else: - condition = translator.HandleExpr(args[0])[0] - return ['#error ' + _to_str(condition)] - return ['#error "Error: Condition is not met."'] - - -class TokenPast: - """## 连接符""" - def __init__(self, left, right): - self.left = left - self.right = right - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.TokenPast() 调用""" - if len(args) >= 2: - # 处理左操作数 - 去掉引号 - if isinstance(args[0], ast.Constant): - left = str(args[0].value) - elif isinstance(args[0], ast.Str): - left = str(args[0].s) - elif isinstance(args[0], ast.Name): - left = args[0].id - else: - left = _to_str(translator.HandleExpr(args[0])[0]) - - # 处理右操作数 - 去掉引号 - if isinstance(args[1], ast.Constant): - right = str(args[1].value) - elif isinstance(args[1], ast.Str): - right = str(args[1].s) - elif isinstance(args[1], ast.Name): - right = args[1].id - else: - right = _to_str(translator.HandleExpr(args[1])[0]) - - # 返回字符串,但用特殊标记包装,让 _AstNodeToStr 能正确处理 - result = left + ' ## ' + right - # 使用一个特殊的类来包装结果,让 _AstNodeToStr 直接返回其值 - class TokenPastResult: - def __init__(self, value): - self.value = value - def __str__(self): - return self.value - return [TokenPastResult(result)] - return [''] - - -class CIf: - """#if 条件编译""" - def __init__(self, condition): - self.condition = condition - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CIf() 调用""" - if args: - condition = translator.HandleExpr(args[0])[0] - return ['#if ' + _to_str(condition)] - return ['#if 0'] - - -class CElif: - """#elif 条件编译""" - def __init__(self, condition): - self.condition = condition - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CElif() 调用""" - if args: - condition = translator.HandleExpr(args[0])[0] - return ['#elif ' + _to_str(condition)] - return ['#else'] - - -class CElse: - """#else 条件编译""" - def __init__(self): - pass - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CElse() 调用""" - return ['#else'] - - -class CEndif: - """#endif 条件编译""" - def __init__(self): - pass - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CEndif() 调用""" - return ['#endif'] - - -class CUndef: - """#undef 取消宏定义""" - def __init__(self, name): - self.name = name - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CUndef(name) 调用""" - import ast - if args: - arg = args[0] - if isinstance(arg, str): - name = arg - elif isinstance(arg, ast.Name): - name = arg.id - elif isinstance(arg, ast.Constant): - name = str(arg.value) - else: - name = str(arg) - return [f'#undef {name}'] - return ['#undef'] - - -class LLVMIR: - """内联 LLVM IR - - 用法: c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - 或: c.LLVMIR(f"%{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - - c.LInp(expr) - 输入操作数,翻译后替换为对应的 LLVM 临时变量名 - c.LOut(expr) - 输出操作数,翻译后替换为对应的 LLVM 临时变量名 - """ - def __init__(self, ir_template, ret_type=None): - self.ir_template = ir_template - self.ret_type = ret_type - - @staticmethod - def HandleCall(translator, args, keywords): - return ['/* LLVMIR */'] - - -class LInp: - """LLVM IR 输入操作数标记 - - 用法: c.LInp(expr) - 标记 expr 为输入操作数 - 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 - """ - def __init__(self, value): - self.value = value - - @staticmethod - def HandleCall(translator, args, keywords): - return [] - - -class LOut: - """LLVM IR 输出操作数标记 - - 用法: c.LOut(expr) - 标记 expr 为输出操作数 - 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 - """ - def __init__(self, value): - self.value = value - - @staticmethod - def HandleCall(translator, args, keywords): - return [] - - -class CPragma: - """#pragma 指令 - - 用于生成 C 语言的 #pragma 指令。 - 例如:c.CPragma("GCC diagnostic push") 生成 #pragma GCC diagnostic push - """ - def __init__(self, directive): - self.directive = directive - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 c.CPragma() 调用""" - if args: - arg = args[0] - if isinstance(arg, ast.Constant): - directive = arg.value - elif isinstance(arg, ast.Str): - directive = arg.s - else: - expr = translator.HandleExpr(arg)[0] - directive = _to_str(expr) - return [f'#pragma {directive}'] - return ['#pragma'] - - -# C 库类字典,用于 HandleCSpecialCall -Library_C = { - 'Asm': Asm, - 'Load': Load, - 'Addr': Addr, - 'Deref': Deref, - 'Set': Set, - 'AsmInp': AsmInp, - 'AsmOut': AsmOut, - 'CDefine': CDefine, - 'CIfndef': CIfndef, - 'CIfdef': CIfdef, - 'CIf': CIf, - 'CElif': CElif, - 'CElse': CElse, - 'CEndif': CEndif, - 'CUndef': CUndef, - 'CError': CError, - 'TokenPast': TokenPast, - 'CReturn': CReturn, - 'CPragma': CPragma, - 'LLVMIR': LLVMIR, - 'LInp': LInp, - 'LOut': LOut, -} - - -class Attribute: - """函数/变量属性装饰器""" - def __init__(self, *attrs): - self.attrs = attrs - - def __call__(self, func): - # 将属性附加到函数上 - func._c_attributes = self.attrs - return func diff --git a/CPython/t.py b/CPython/t.py deleted file mode 100644 index 495d5e8..0000000 --- a/CPython/t.py +++ /dev/null @@ -1,1283 +0,0 @@ -# 类型定义模块 - -import re -import types -from typing import TypeVar, Generic, TypeAlias - - -# ============================================================================= -# 类型映射常量 -# ============================================================================= - -# 类型映射常量(由 _build_type_maps() 在模块末尾自动生成) -_BASIC_TYPES_MAP = {} -_T_TYPE_PATTERNS = [] - -def _build_type_maps(): - global _BASIC_TYPES_MAP, _T_TYPE_PATTERNS - for _name in dir(): - _obj = eval(_name) - if isinstance(_obj, type) and issubclass(_obj, CType) and _obj is not CType: - try: - _inst = _obj() - _cname = getattr(_inst, 'CName', '') - if _cname and _obj.IsBasicType(): - _BASIC_TYPES_MAP[_cname] = _cname - _T_TYPE_PATTERNS.append((_name, _cname)) - except Exception: - pass - - -# ============================================================================= -# CType 基类 -# ============================================================================= - -class CType: - """C 类型基类""" - - PREFIX = 'prefix' - BASE = 'base' - POINTER = 'ptr' - ARRAY = 'array' - NAMED = 'named' - STORAGE_CLASS = 'storage_class' - TYPE_QUALIFIER = 'type_qualifier' - - position = frozenset({BASE}) # 类属性,支持联合类型如 BASE | SPECIAL - - def __init__(self, value=None, *types): - self.value = value - self.types = types - self.Name = '' - self.IsBasicType = False - self.IsPointer = False - self.IsSigned = None - self.Size = None - if not hasattr(self, 'CName'): - self.CName = '' - - def GetPositions(self) -> frozenset: - """获取 position 的 frozenset 形式""" - return self.position - - @classmethod - def HasPosition(cls, pos) -> bool: - """检查是否包含指定的位置""" - return pos in cls.position - - @classmethod - def IsNamed(cls) -> bool: - """检查是否是命名类型(struct/union/enum/typedef 等)""" - return cls.NAMED in cls.position - - @classmethod - def IsStorageClass(cls) -> bool: - """检查是否是存储类修饰符""" - return cls.STORAGE_CLASS in cls.position - - @classmethod - def IsTypeQualifier(cls) -> bool: - """检查是否是类型限定符""" - return cls.TYPE_QUALIFIER in cls.position - - @classmethod - def IsBasicType(cls) -> bool: - """检查是否是基本类型""" - return cls.BASE in cls.position - - @classmethod - def IsPrefix(cls) -> bool: - """检查是否是前缀类型""" - return cls.PREFIX in cls.position - - def rfind(self, s): - """注解""" - pass - - def get_position(self): - """获取类型在声明中的位置""" - return self.position - - def GetCAame(self): - """获取 C 类型名称""" - return self.CName - - def __merge__(self, types): - return types - - def __or__(self, other): - return [self, other] - - def __set_default__(self, **kwargs): - """设置默认值/初始值,用于 static/global 变量的初始化 - - Args: - **kwargs: 成员名称和值的键值对 - - Returns: - 包含默认值信息的 CTypeDefault 对象 - """ - return CTypeDefault(self, **kwargs) - - @classmethod - def FromAnnotation(cls, AnnotationStr, TypeName=''): - """从类型注解字符串解析类型信息 - - Args: - AnnotationStr: 类型注解的字符串表示(ast.dump结果) - TypeName: 类型名称(可选) - - Returns: - CType 实例 - """ - ctype = cls() - - # 检查是否是基本类型 - if TypeName in _BASIC_TYPES_MAP: - ctype.IsBasicType = True - ctype.Name = _BASIC_TYPES_MAP[TypeName] - else: - for pattern, c_name in _T_TYPE_PATTERNS: - if pattern in AnnotationStr: - ctype.IsBasicType = True - ctype.Name = c_name - break - - # 检查是否包含指针 - if 'CPtr' in AnnotationStr: - ctype.IsPointer = True - - return ctype - - @classmethod - def FromTypeName(cls, TypeName): - """从类型名称创建 CType - - Args: - TypeName: 类型名称 - - Returns: - CType 实例 - """ - ctype = cls() - - if TypeName in _BASIC_TYPES_MAP: - ctype.IsBasicType = True - ctype.Name = _BASIC_TYPES_MAP[TypeName] - - return ctype - - def GetFullType(self, VarName='', ArraySizeStr=''): - """获取完整的类型声明字符串 - - Args: - VarName: 变量名 - ArraySizeStr: 数组大小字符串 - - Returns: - 完整的类型声明字符串 - """ - ptr_str = '*' if self.IsPointer else '' - if VarName: - return f'{self.Name}{ptr_str} {VarName}{ArraySizeStr}' - return f'{self.Name}{ptr_str}' - - def __repr__(self): - ptr_str = '*' if self.IsPointer else '' - return f'CType({self.Name}{ptr_str}, IsBasicType={self.IsBasicType})' - -class CChar(CType): - def __init__(self, value=None): - self.CName = 'char' - super().__init__(value) - self.IsSigned = True - self.Size = 8 - -class CInt(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int' - super().__init__(value) - self.IsSigned = True - self.Size = 32 - -class CShort(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'short' - super().__init__(value) - self.IsSigned = True - self.Size = 16 - -class CLong(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'long' - super().__init__(value) - self.IsSigned = True - self.Size = 64 - -class CFloat(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float' - super().__init__(value) - self.IsSigned = None - self.Size = 32 - -class CDouble(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'double' - super().__init__(value) - self.IsSigned = None - self.Size = 64 - -class CFloat8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float8_t' - super().__init__(value) - self.IsSigned = None - self.Size = 8 - -class CFloat16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float16_t' - super().__init__(value) - self.IsSigned = None - self.Size = 16 - -class CFloat32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float32_t' - super().__init__(value) - self.IsSigned = None - self.Size = 32 - -class CFloat64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float64_t' - super().__init__(value) - self.IsSigned = None - self.Size = 64 - -class CFloat128T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float128_t' - super().__init__(value) - self.IsSigned = None - self.Size = 128 - -class CVoid(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'void' - super().__init__(value) - self.IsSigned = None - self.Size = 0 - -class CUnsigned(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned' - super().__init__(value) - self.IsSigned = False - self.Size = 32 - -class CUnsignedChar(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned char' - super().__init__(value) - self.IsSigned = False - self.Size = 8 - -class CUnsignedInt(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned int' - super().__init__(value) - self.IsSigned = False - self.Size = 32 - -class CUnsignedShort(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned short' - super().__init__(value) - self.IsSigned = False - self.Size = 16 - -class CUnsignedLong(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned long' - super().__init__(value) - self.IsSigned = False - self.Size = 64 - -class CSignedChar(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'signed char' - super().__init__(value) - self.IsSigned = True - self.Size = 8 - -class CStruct(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None, name=None): - self.CName = f'struct {name}' if name else 'struct' - super().__init__(value) - -class CUnion(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'union' - super().__init__(value) - -class CEnum(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'enum' - super().__init__(value) - self.b = 1 - -Enum = CEnum # 别名,允许使用 t.Enum - -''' -class Object(CType): - """Python 对象类型,用于支持类方法外联函数""" - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'struct' - super().__init__(value) - def __call__(self, cls): - return cls -''' -def Object(): - pass - -def CVTable(): - pass - -CTypedef = TypeAlias - -class _CTypedef(CType): - position = frozenset({CType.PREFIX, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'typedef' - super().__init__(value) - - -class CAuto(CType): - position = frozenset({CType.PREFIX}) - def __init__(self, value=None): - self.CName = 'auto' - super().__init__(value) - -class CRegister(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'register' - super().__init__(value) - -class CStatic(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'static' - super().__init__(value) - -class CExtern(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'extern' - super().__init__(value) - -class CConst(CType): - position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) - def __init__(self, value=None): - self.CName = 'const' - super().__init__(value) - -class CInline(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'inline' - super().__init__(value) - -class CExport(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'export' - super().__init__(value) - -class CVolatile(CType): - position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) - def __init__(self, value=None): - self.CName = 'volatile' - super().__init__(value) - -class CSizeT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'size_t' - super().__init__(value) - self.IsSigned = False - self.Size = 64 - -class CInt8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int8_t' - super().__init__(value) - self.IsSigned = True - self.Size = 8 - -class CInt16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int16_t' - super().__init__(value) - self.IsSigned = True - self.Size = 16 - -class CInt32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int32_t' - super().__init__(value) - self.IsSigned = True - self.Size = 32 - -class CInt64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int64_t' - super().__init__(value) - self.IsSigned = True - self.Size = 64 - -class CUInt8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint8_t' - super().__init__(value) - self.IsSigned = False - self.Size = 8 - -class CUInt16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint16_t' - super().__init__(value) - self.IsSigned = False - self.Size = 16 - -class CUInt32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint32_t' - super().__init__(value) - self.IsSigned = False - self.Size = 32 - -class CUInt64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint64_t' - super().__init__(value) - self.IsSigned = False - self.Size = 64 - -class CIntPtrT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'intptr_t' - super().__init__(value) - self.IsSigned = True - self.Size = 64 - -class CUIntPtrT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uintptr_t' - super().__init__(value) - self.IsSigned = False - self.Size = 64 - -class CPtrDiffT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'ptrdiff_t' - super().__init__(value) - self.IsSigned = True - self.Size = 64 - -class CWCharT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'wchar_t' - super().__init__(value) - self.IsSigned = True - self.Size = 32 - -class CChar8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char8_t' - super().__init__(value) - self.IsSigned = False - self.Size = 8 - -class CChar16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char16_t' - super().__init__(value) - self.IsSigned = False - self.Size = 16 - -class CChar32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char32_t' - super().__init__(value) - self.IsSigned = False - self.Size = 32 - -class CBool(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'bool' - super().__init__(value) - self.IsSigned = False - self.Size = 8 - -class CComplex(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '_Complex' - super().__init__(value) - -class CImaginary(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '_Imaginary' - super().__init__(value) - -T = TypeVar("T") -Callable = Generic[T] - -class CPtr(CType, Generic[T]): - position = frozenset({CType.POINTER}) - def __init__(self, value=None): - self.CName = '*' - super().__init__(value) - -class CTypeDefault(CType): - """用于存储 C 类型默认值/初始化的包装类 - - 当使用 t.CStatic.__set_default__(open=mouse_open, ...) 时创建 - """ - def __init__(self, BaseType, **kwargs): - super().__init__() - self.BaseType = BaseType - self.defaults = kwargs - self.CName = BaseType.CName if hasattr(BaseType, 'CName') else '' - self.position = BaseType.position if hasattr(BaseType, 'position') else CType.BASE - - def __repr__(self): - return f'CTypeDefault({self.BaseType}, {self.defaults})' - -class CArrayPtr(CType): - position = frozenset({CType.POINTER}) - def __init__(self, value=None): - self.CName = '(*)' # 特殊标记表示数组指针 - super().__init__(value) - -class CDefine(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '#define' - super().__init__(value) - -class CPass(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '' - super().__init__(value) - -class State(CType): - """状态标记,用于仅声明不定义,等价于 CExport | CExtern""" - position = frozenset({CType.PREFIX}) - - @staticmethod - def HandleCall(translator, args, keywords): - """处理 t.State() 调用""" - return ['t.State'] - -class Anonymous: - def __init__(): - pass - -class Postdefinition: - def __init__(self, c): - pass - -class Bit: - def __init__(self, i): - pass - -class BigEndian(CType): - """大端序(Big-Endian)字节序标记类 - - 用于标记结构体成员应使用大端序存储。 - 在小端序平台(如x86)上读取时,会自动进行字节交换。 - - 用法示例: - class MyStruct: - a: t.CInt | t.BigEndian # 大端序存储的整数 - """ - IsSigned = True - Size = 4 - Align = 4 - -class LittleEndian(CType): - """小端序(Little-Endian)字节序标记类 - - 用于标记结构体成员应使用小端序存储。 - 在小端序平台(如x86)上读取时,不需要进行字节交换。 - - 用法示例: - class MyStruct: - b: t.CInt | t.LittleEndian # 小端序存储的整数 - """ - IsSigned = True - Size = 4 - Align = 4 - -class ASM_DESCR: - """内嵌 ASM 破坏描述符类 - - 定义了所有可能的破坏描述符和约束字符,用于 GCC 内嵌汇编 - """ - # 操作数修饰符 - MODIFIER_OUTPUT = '=' # 输出操作数 - MODIFIER_READWRITE = '+' # 读写操作数 - MODIFIER_INPUT = '' # 输入操作数(默认) - MODIFIER_GLOBAL = '&' # 全局操作数 - - # 寄存器约束(32位命名) - REG_ANY = 'r' # 任何通用寄存器 - REG_EAX = 'a' # EAX/RAX 寄存器 - REG_EBX = 'b' # EBX/RBX 寄存器 - REG_ECX = 'c' # ECX/RCX 寄存器 - REG_EDX = 'd' # EDX/RDX 寄存器 - REG_ESI = 'S' # ESI/RSI 寄存器 - REG_EDI = 'D' # EDI/RDI 寄存器 - REG_STACK = 'q' # 任何通用寄存器(EAX, EBX, ECX, EDX) - REG_FLOAT = 'f' # 浮点寄存器 - REG_MMX = 'y' # MMX 寄存器 - REG_XMM = 'x' # XMM 寄存器 - - # 寄存器约束(64位命名,GCC约束字符与32位相同) - REG_RAX = 'a' # RAX 寄存器 - REG_RBX = 'b' # RBX 寄存器 - REG_RCX = 'c' # RCX 寄存器 - REG_RDX = 'd' # RDX 寄存器 - REG_RSI = 'S' # RSI 寄存器 - REG_RDI = 'D' # RDI 寄存器 - REG_R8 = 'r' # R8 寄存器(需通过r约束+显式指定) - REG_R9 = 'r' # R9 寄存器 - REG_R10 = 'r' # R10 寄存器 - REG_R11 = 'r' # R11 寄存器 - REG_R12 = 'r' # R12 寄存器 - REG_R13 = 'r' # R13 寄存器 - REG_R14 = 'r' # R14 寄存器 - REG_R15 = 'r' # R15 寄存器 - REG_RBP = 'r' # RBP 寄存器 - REG_RSP = 'r' # RSP 寄存器 - - # 内存约束 - MEMORY = 'm' # 内存操作数 - - # 立即数约束 - IMMEDIATE = 'i' # 立即数 - IMMEDIATE_CONST = 'n' # 常量立即数 - - # 综合约束 - ANY = 'g' # 任何通用寄存器、内存或立即数 - MEMORY_OR_REG = 'o' # 内存或寄存器 - - # 破坏描述符(clobber list) - CLOBBER_EAX = 'eax' # 破坏 EAX/RAX 寄存器 - CLOBBER_EBX = 'ebx' # 破坏 EBX/RBX 寄存器 - CLOBBER_ECX = 'ecx' # 破坏 ECX/RCX 寄存器 - CLOBBER_EDX = 'edx' # 破坏 EDX/RDX 寄存器 - CLOBBER_ESI = 'esi' # 破坏 ESI/RSI 寄存器 - CLOBBER_EDI = 'edi' # 破坏 EDI/RDI 寄存器 - CLOBBER_EBP = 'ebp' # 破坏 EBP/RBP 寄存器 - CLOBBER_ESP = 'esp' # 破坏 ESP/RSP 寄存器 - CLOBBER_AL = 'al' # 破坏 AL 寄存器(EAX/RAX 低8位) - CLOBBER_AH = 'ah' # 破坏 AH 寄存器(EAX/RAX 高8位) - CLOBBER_BL = 'bl' # 破坏 BL 寄存器(EBX/RBX 低8位) - CLOBBER_BH = 'bh' # 破坏 BH 寄存器(EBX/RBX 高8位) - CLOBBER_CL = 'cl' # 破坏 CL 寄存器(ECX/RCX 低8位) - CLOBBER_CH = 'ch' # 破坏 CH 寄存器(ECX/RCX 高8位) - CLOBBER_DL = 'dl' # 破坏 DL 寄存器(EDX/RDX 低8位) - CLOBBER_DH = 'dh' # 破坏 DH 寄存器(EDX/RDX 高8位) - CLOBBER_CC = 'cc' # 破坏条件代码寄存器(标志寄存器) - CLOBBER_MEMORY = 'memory' # 破坏内存(表示汇编代码修改了内存) - # 16 位寄存器破坏描述符 - CLOBBER_AX = 'ax' # 破坏 AX 寄存器 - CLOBBER_BX = 'bx' # 破坏 BX 寄存器 - CLOBBER_CX = 'cx' # 破坏 CX 寄存器 - CLOBBER_DX = 'dx' # 破坏 DX 寄存器 - CLOBBER_SI = 'si' # 破坏 SI 寄存器 - CLOBBER_DI = 'di' # 破坏 DI 寄存器 - CLOBBER_BP = 'bp' # 破坏 BP 寄存器 - - # 64位寄存器破坏描述符 - CLOBBER_RAX = 'rax' # 破坏 RAX 寄存器 - CLOBBER_RBX = 'rbx' # 破坏 RBX 寄存器 - CLOBBER_RCX = 'rcx' # 破坏 RCX 寄存器 - CLOBBER_RDX = 'rdx' # 破坏 RDX 寄存器 - CLOBBER_RSI = 'rsi' # 破坏 RSI 寄存器 - CLOBBER_RDI = 'rdi' # 破坏 RDI 寄存器 - CLOBBER_RBP = 'rbp' # 破坏 RBP 寄存器 - CLOBBER_RSP = 'rsp' # 破坏 RSP 寄存器 - CLOBBER_R8 = 'r8' # 破坏 R8 寄存器 - CLOBBER_R9 = 'r9' # 破坏 R9 寄存器 - CLOBBER_R10 = 'r10' # 破坏 R10 寄存器 - CLOBBER_R11 = 'r11' # 破坏 R11 寄存器 - CLOBBER_R12 = 'r12' # 破坏 R12 寄存器 - CLOBBER_R13 = 'r13' # 破坏 R13 寄存器 - CLOBBER_R14 = 'r14' # 破坏 R14 寄存器 - CLOBBER_R15 = 'r15' # 破坏 R15 寄存器 - - # 预定义的组合约束(32位命名) - OUTPUT_REG = '=r' # 输出操作数,使用任何通用寄存器 - OUTPUT_MEM = '=m' # 输出操作数,使用内存 - OUTPUT_EAX = '=a' # 输出操作数,使用 EAX/RAX 寄存器 - OUTPUT_EBX = '=b' # 输出操作数,使用 EBX/RBX 寄存器 - OUTPUT_ECX = '=c' # 输出操作数,使用 ECX/RCX 寄存器 - OUTPUT_EDX = '=d' # 输出操作数,使用 EDX/RDX 寄存器 - OUTPUT_ESI = '=S' # 输出操作数,使用 ESI/RSI 寄存器 - OUTPUT_EDI = '=D' # 输出操作数,使用 EDI/RDI 寄存器 - - # 预定义的组合约束(64位命名) - OUTPUT_RAX = '=a' # 输出操作数,使用 RAX 寄存器 - OUTPUT_RBX = '=b' # 输出操作数,使用 RBX 寄存器 - OUTPUT_RCX = '=c' # 输出操作数,使用 RCX 寄存器 - OUTPUT_RDX = '=d' # 输出操作数,使用 RDX 寄存器 - OUTPUT_RSI = '=S' # 输出操作数,使用 RSI 寄存器 - OUTPUT_RDI = '=D' # 输出操作数,使用 RDI 寄存器 - - INPUT_REG = 'r' # 输入操作数,使用任何通用寄存器 - INPUT_MEM = 'm' # 输入操作数,使用内存 - INPUT_EAX = 'a' # 输入操作数,使用 EAX/RAX 寄存器 - INPUT_EBX = 'b' # 输入操作数,使用 EBX/RBX 寄存器 - INPUT_ECX = 'c' # 输入操作数,使用 ECX/RCX 寄存器 - INPUT_EDX = 'd' # 输入操作数,使用 EDX/RDX 寄存器 - INPUT_ESI = 'S' # 输入操作数,使用 ESI/RSI 寄存器 - INPUT_EDI = 'D' # 输入操作数,使用 EDI/RDI 寄存器 - INPUT_IMM = 'i' # 输入操作数,使用立即数 - INPUT_ANY = 'g' # 输入操作数,使用任何通用寄存器、内存或立即数 - - # 输入约束(64位命名) - INPUT_RAX = 'a' # 输入操作数,使用 RAX 寄存器 - INPUT_RBX = 'b' # 输入操作数,使用 RBX 寄存器 - INPUT_RCX = 'c' # 输入操作数,使用 RCX 寄存器 - INPUT_RDX = 'd' # 输入操作数,使用 RDX 寄存器 - INPUT_RSI = 'S' # 输入操作数,使用 RSI 寄存器 - INPUT_RDI = 'D' # 输入操作数,使用 RDI 寄存器 - - # 所有单独约束字符列表 - ALL_CONSTRAINTS = [ - # 操作数修饰符 - MODIFIER_OUTPUT, MODIFIER_READWRITE, MODIFIER_INPUT, MODIFIER_GLOBAL, - - # 寄存器约束 - REG_ANY, REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_ESI, REG_EDI, - REG_STACK, REG_FLOAT, REG_MMX, REG_XMM, - - # 内存约束 - MEMORY, - - # 立即数约束 - IMMEDIATE, IMMEDIATE_CONST, - - # 综合约束 - ANY, MEMORY_OR_REG - ] - - # 所有破坏描述符列表 - ALL_CLOBBERS = [ - CLOBBER_EAX, CLOBBER_EBX, CLOBBER_ECX, CLOBBER_EDX, - CLOBBER_ESI, CLOBBER_EDI, CLOBBER_EBP, CLOBBER_ESP, - CLOBBER_CC, CLOBBER_MEMORY, - CLOBBER_RAX, CLOBBER_RBX, CLOBBER_RCX, CLOBBER_RDX, - CLOBBER_RSI, CLOBBER_RDI, CLOBBER_RBP, CLOBBER_RSP, - CLOBBER_R8, CLOBBER_R9, CLOBBER_R10, CLOBBER_R11, - CLOBBER_R12, CLOBBER_R13, CLOBBER_R14, CLOBBER_R15 - ] - - # 所有描述符列表 - ALL = ALL_CONSTRAINTS + ALL_CLOBBERS - - -# 定义 ASM_LIST,包含所有可能的汇编约束字符 -ASM_LIST = ASM_DESCR.ALL - - -class attr: - """C 语言 __attribute__ 属性操作类型""" - - @staticmethod - def noreturn(): - return "noreturn" - - @staticmethod - def format(printf, arg1, arg2): - return f"format({printf}, {arg1}, {arg2})" - - @staticmethod - def section(name): - return f'section("{name}")' - - @staticmethod - def aligned(bytes): - return f"aligned({bytes})" - - @staticmethod - def packed(): - return "packed" - - @staticmethod - def unused(): - return "unused" - - @staticmethod - def used(): - return "used" - - @staticmethod - def weak(): - return "weak" - - @staticmethod - def alias(name): - return f'alias("{name}")' - - @staticmethod - def visibility(type): - return f'visibility("{type}")' - - @staticmethod - def constructor(): - return "constructor" - - @staticmethod - def destructor(): - return "destructor" - - @staticmethod - def always_inline(): - return "always_inline" - - @staticmethod - def noinline(): - return "noinline" - - @staticmethod - def pure(): - return "pure" - - @staticmethod - def const(): - return "const" - - @staticmethod - def malloc(): - return "malloc" - - @staticmethod - def alloc_size(n): - return f"alloc_size({n})" - - @staticmethod - def warn_unused_result(): - return "warn_unused_result" - - @staticmethod - def deprecated(msg=None): - if msg: - return f'deprecated("{msg}")' - return "deprecated" - - @staticmethod - def fallthrough(): - return "fallthrough" - - @staticmethod - def likely(): - return "likely" - - @staticmethod - def unlikely(): - return "unlikely" - - @staticmethod - def hot(): - return "hot" - - @staticmethod - def cold(): - return "cold" - - @staticmethod - def interrupt(): - return "interrupt" - - @staticmethod - def naked(): - return "naked" - - @staticmethod - def sentinel(n=0): - return f"sentinel({n})" - - @staticmethod - def nonnull(*args): - if args: - return f"nonnull({', '.join(map(str, args))})" - return "nonnull" - - @staticmethod - def returns_nonnull(): - return "returns_nonnull" - - @staticmethod - def access(mode, *args): - return f"access({mode}, {', '.join(map(str, args))})" - - @staticmethod - def cleanup(func): - return f'cleanup({func})' - - @staticmethod - def transparent_union(): - return "transparent_union" - - @staticmethod - def mode(mode_name): - return f"mode({mode_name})" - - @staticmethod - def vector_size(bytes): - return f"vector_size({bytes})" - - @staticmethod - def target(string): - return f'target("{string}")' - - @staticmethod - def optimize(level): - return f'optimize("{level}")' - - @staticmethod - def no_instrument_function(): - return "no_instrument_function" - - @staticmethod - def no_sanitize(type): - return f"no_sanitize({type})" - - @staticmethod - def no_stack_protector(): - return "no_stack_protector" - - @staticmethod - def stack_protector(): - return "stack_protector" - - @staticmethod - def error(msg): - return f'error("{msg}")' - - @staticmethod - def warning(msg): - return f'warning("{msg}")' - - class llvm: - """LLVM 函数属性描述符 - - 用于在返回类型注解中指定 LLVM 函数属性。 - 例如: def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind: - """ - - class nobuiltin: - CName = '#attr.llvm.nobuiltin' - - class nounwind: - CName = '#attr.llvm.nounwind' - - class noredzone: - CName = '#attr.llvm.noredzone' - - class willreturn: - CName = '#attr.llvm.willreturn' - - class mustprogress: - CName = '#attr.llvm.mustprogress' - - class optnone: - CName = '#attr.llvm.optnone' - - class noinline: - CName = '#attr.llvm.noinline' - - class alwaysinline: - CName = '#attr.llvm.alwaysinline' - - class readnone: - CName = '#attr.llvm.readnone' - - class readonly: - CName = '#attr.llvm.readonly' - - class writeonly: - CName = '#attr.llvm.writeonly' - - class inaccessiblememonly: - CName = '#attr.llvm.inaccessiblememonly' - - class inaccessiblemem_or_argmemonly: - CName = '#attr.llvm.inaccessiblemem_or_argmemonly' - - -def NewCType(size, signed): - ct = CType() - ct.Size = size - ct.IsSigned = signed - return ct - -i1 = NewCType(1, True) -i8 = NewCType(8, True) -i16 = NewCType(16, True) -i32 = NewCType(32, True) -i64 = NewCType(64, True) - -u1 = NewCType(1, False) -u8 = NewCType(8, False) -u16 = NewCType(16, False) -u32 = NewCType(32, False) -u64 = NewCType(64, False) - - -class CTypeRegistry: - """基于 CType 元属性的类型注册表,替代手动映射表 - - 利用 CType 子类的 position/IsSigned/Size 元属性自动推导: - - LLVM IR 类型字符串 (如 'i32', 'double', 'i8*') - - C 类型名称 (如 'int', 'unsigned char', 'long long') - - Python CType 类引用 (如 t.CInt32T) - """ - - _name_to_class = None - _cname_to_class = None - - @classmethod - def _build(cls): - if cls._name_to_class is not None: - return - import sys - mod = sys.modules.get(__name__) - if mod is None: - return - cls._name_to_class = {} - cls._cname_to_class = {} - for name, obj in vars(mod).items(): - if not isinstance(obj, type) or not issubclass(obj, CType) or obj is CType: - continue - if obj in (CTypeDefault, BigEndian, LittleEndian): - continue - try: - inst = obj() - except Exception: - continue - pos = getattr(obj, 'position', frozenset()) - if CType.PREFIX in pos and CType.BASE not in pos: - continue - if CType.POINTER in pos and CType.BASE not in pos: - cls._name_to_class[name] = obj - continue - if getattr(inst, 'Size', None) is not None or getattr(inst, 'CName', ''): - cls._name_to_class[name] = obj - cname = getattr(inst, 'CName', '') - if cname and cname not in cls._cname_to_class: - cls._cname_to_class[cname] = obj - - @classmethod - def GetClassByName(cls, name: str): - """根据 Python 类名获取 CType 类 (如 'CInt32T' -> t.CInt32T)""" - cls._build() - return cls._name_to_class.get(name) - - @classmethod - def GetClassByCName(cls, cname: str): - """根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T)""" - cls._build() - return cls._cname_to_class.get(cname) - - @staticmethod - def CTypeToLLVM(ctype_class) -> str: - """从 CType 类的元属性推导 LLVM IR 类型字符串 - - 规则: - - position 含 POINTER 且不含 BASE → 'i8*' - - position 含 PREFIX 且不含 BASE → '' (修饰符,无LLVM类型) - - Size == 0 且 IsSigned is None → 'void' - - IsSigned is None 且 Size > 0 → 浮点: half/float/double/fp128 - - IsSigned is True/False 且 Size > 0 → 整数: i{Size} - """ - if ctype_class is None: - return 'i8*' - pos = getattr(ctype_class, 'position', frozenset()) - if CType.POINTER in pos and CType.BASE not in pos: - return 'i8*' - if CType.PREFIX in pos and CType.BASE not in pos: - return '' - try: - inst = ctype_class() - except Exception: - return 'i8*' - size = getattr(inst, 'Size', None) - is_signed = getattr(inst, 'IsSigned', None) - if size is None or size == 0: - if is_signed is None: - return 'void' - return 'i8*' - if is_signed is None: - float_map = {8: 'half', 16: 'half', 32: 'float', 64: 'double', 128: 'fp128'} - return float_map.get(size, f'f{size}') - return f'i{size}' - - @staticmethod - def CTypeToCName(ctype_class) -> str: - """从 CType 类推导 C 类型名称 (用于 printf 格式化等) - - 规则: - - IsSigned is None 且 Size > 0 → 浮点: float/double/long double - - IsSigned is True → 有符号整数: char/short/int/long long - - IsSigned is False → 无符号整数: unsigned char/unsigned short/unsigned int/unsigned long long - """ - if ctype_class is None: - return '' - try: - inst = ctype_class() - except Exception: - return '' - size = getattr(inst, 'Size', None) - is_signed = getattr(inst, 'IsSigned', None) - if size is None: - return '' - if is_signed is None and size > 0: - float_cname = {32: 'float', 64: 'double', 128: 'long double'} - return float_cname.get(size, 'double') - int_cname_signed = {8: 'char', 16: 'short', 32: 'int', 64: 'long long'} - int_cname_unsigned = {8: 'unsigned char', 16: 'unsigned short', 32: 'unsigned int', 64: 'unsigned long long'} - if is_signed: - return int_cname_signed.get(size, 'int') - else: - return int_cname_unsigned.get(size, 'unsigned int') - - @classmethod - def NameToLLVM(cls, name: str) -> str: - """根据 Python 类型名推导 LLVM IR 类型 (如 'CFloat64T' -> 'double') - - 修饰符类型 (CConst, CStatic 等) 返回空字符串。 - 指针类型 (CPtr) 返回 'i8*'。 - 未知类型返回 None。 - """ - cls._build() - import sys - mod = sys.modules.get(__name__) - if mod and hasattr(mod, name): - obj = getattr(mod, name) - if isinstance(obj, type) and issubclass(obj, CType): - return cls.CTypeToLLVM(obj) - return None - - @classmethod - def NameToCName(cls, name: str) -> str: - """根据 Python 类型名推导 C 类型名 (如 'CInt32T' -> 'int')""" - ctype_class = cls.GetClassByName(name) - if ctype_class is not None: - return cls.CTypeToCName(ctype_class) - return None - - @classmethod - def CNameToClass(cls, cname: str): - """根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T, 'unsigned char' -> t.CUnsignedChar)""" - cls._build() - return cls._cname_to_class.get(cname) - - @classmethod - def ResolveName(cls, name: str): - """解析类型名到 (CType类, 指针层级) - - 支持的格式: - - Python 类名: 'CInt32T' -> (t.CInt32T, 0) - - C 类型名: 'int32_t' -> (t.CInt32T, 0) - - stdint 大写别名: 'INT32' -> (t.CInt32T, 0) - - 指针别名: 'INT32PTR' -> (t.CInt32T, 1) - - 大写别名: 'BYTE' -> (t.CUnsignedChar, 0), 'DWORD' -> (t.CUInt32T, 0) - - 浮点别名: 'FLOAT64' -> (t.CFloat64T, 0) - - void指针: 'VOIDPTR' -> (t.CVoid, 1) - """ - cls._build() - direct = cls._name_to_class.get(name) - if direct is not None: - pos = getattr(direct, 'position', frozenset()) - ptr_level = 1 if CType.POINTER in pos and CType.BASE not in pos else 0 - return (direct, ptr_level) - cnameres = cls._cname_to_class.get(name) - if cnameres is not None: - return (cnameres, 0) - if name.endswith('PTR'): - base_name = name[:-3] - base_result = cls.ResolveName(base_name) - if base_result is not None: - return (base_result[0], base_result[1] + 1) - if name.startswith('FLOAT') and name[5:].isdigit(): - bits = int(name[5:]) - float_name = f'CFloat{bits}T' - float_cls = cls._name_to_class.get(float_name) - if float_cls is not None: - return (float_cls, 0) - _UPPER_ALIAS = { - 'BYTE': 'CUInt8T', 'INT8': 'CInt8T', 'UINT8': 'CUInt8T', - 'WORD': 'CUInt16T', 'INT16': 'CInt16T', 'UINT16': 'CUInt16T', - 'DWORD': 'CUInt32T', 'INT32': 'CInt32T', 'UINT32': 'CUInt32T', - 'UINT': 'CUnsignedInt', 'INT': 'CInt', - 'QWORD': 'CUInt64T', 'INT64': 'CInt64T', 'UINT64': 'CUInt64T', - 'INTPTR': 'CIntPtrT', 'UINTPTR': 'CUIntPtrT', - 'SIZE_T': 'CSizeT', 'SSIZE_T': 'CPtrDiffT', 'PTRDIFF_T': 'CPtrDiffT', - 'VOID': 'CVoid', - } - alias = _UPPER_ALIAS.get(name) - if alias: - alias_cls = cls._name_to_class.get(alias) - if alias_cls is not None: - return (alias_cls, 0) - return None - - -_build_type_maps() \ No newline at end of file diff --git a/Projectrans.py b/Projectrans.py index 0b8f3d4..7a86880 100644 --- a/Projectrans.py +++ b/Projectrans.py @@ -1,3742 +1,24 @@ #!/usr/bin/env python3 -""" -ProjectTrans.py - 工程级 TransPyC 翻译器 - -两阶段翻译流程: - 阶段一:从源文件生成声明接口 .pyi(仅有签名)和 .stub.ll(仅有声明) - 阶段二:使用声明接口翻译源文件,嵌入 .stub.ll 声明,生成含代码的 .ll 并编译为 .obj - -SHA1 = SHA1(source file content) -""" - +"""ProjectTrans.py - 工程级 TransPyC 翻译器""" import sys import os -import re -import hashlib -import shutil -from typing import List -import subprocess -import tempfile -import ast -import traceback -import json -from lib.core.Handles.HandlesBase import CTypeInfo -from lib.includes import t -from pathlib import Path - sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -import TransPyC -from StubGen import PythonToStubConverter -from lib.core.logger import Logger, LogLevel, set_logger - -# 创建全局日志实例 -logger = Logger( - name="TransPyC", - log_file="build.log", - level=LogLevel.INFO, - use_colors=True +from lib.Projectrans import ( + compute_sha1, _check_annotation_for_export, sha1_file, + get_file_dependencies, find_reachable_files_from_entries, + topological_sort_files, Phase1Generator, DeclarationGenerator, + Phase2Translator, _parallel_translate_worker, + save_sha1_map, Load_sha1_map, Load_project_config, resolve_paths, main ) -set_logger(logger) - - -def compute_sha1(content: str) -> str: - return hashlib.sha1(content.encode('utf-8')).hexdigest()[:16] - - -def _check_annotation_for_export(annotation) -> bool: - """递归检查类型注解中是否包含 CExport""" - if annotation is None: - return False - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr == 'CExport': - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return _check_annotation_for_export(annotation.left) or _check_annotation_for_export(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id == 'CExport' - return False - - -def sha1_file(filepath: str) -> str: - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - return compute_sha1(content) - - -def get_file_dependencies(filepath: str, src_root: str) -> set: - """解析 Python 文件的导入依赖""" - dependencies = set() - try: - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - tree = ast.parse(content) - for node in ast.walk(tree): - if isinstance(node, ast.Import): - for alias in node.names: - module = alias.name - dependencies.add(module) - elif isinstance(node, ast.ImportFrom): - if node.module: - module = node.module - if node.level > 0: - # from .module import name → 依赖 pkg.module(模块本身) - pkg_dir = os.path.dirname(filepath) - pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') - if pkg_rel == '.': - pkg_rel = '' - if pkg_rel: - dep_module = f'{pkg_rel}.{module}' - else: - dep_module = module - dependencies.add(dep_module) - else: - if not module.startswith('_'): - dependencies.add(module) - elif node.level > 0 and node.names: - # from . import name → 依赖 pkg.name(子模块) - for alias in node.names: - pkg_dir = os.path.dirname(filepath) - pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') - if pkg_rel == '.': - pkg_rel = '' - dep_module = f'{pkg_rel}.{alias.name}' if pkg_rel else alias.name - dependencies.add(dep_module) - except Exception: - pass - return dependencies - - -def find_reachable_files_from_entries(src_root: str, entry_files: list) -> set: - """从入口文件出发,找出所有可达的 .py 文件(通过导入关系)""" - all_files = {} # module_name -> filepath - for root, dirs, files in os.walk(src_root): - dirs[:] = [d for d in dirs if d not in ('__pycache__',)] - for file in files: - if file.endswith('.py'): - filepath = os.path.join(root, file) - rel = os.path.relpath(filepath, src_root) - module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') - if filepath.endswith('__init__.py'): - all_files[module] = filepath - parent_module = module.rsplit('.', 1)[0] if '.' in module else module - if parent_module not in all_files or not all_files[parent_module].endswith('__init__.py'): - all_files[parent_module] = filepath - elif module not in all_files: - all_files[module] = filepath - top_module = module.split('.')[0] - if top_module not in all_files: - all_files[top_module] = filepath - - reachable = set() - queue = list(entry_files) - - while queue: - current = queue.pop(0) - if current in reachable: - continue - reachable.add(current) - deps = get_file_dependencies(current, src_root) - for dep in deps: - if dep in all_files and all_files[dep] not in reachable: - queue.append(all_files[dep]) - else: - for key, val in all_files.items(): - if key.endswith('.' + dep) or key == dep: - if val not in reachable: - queue.append(val) - break - - return reachable - - -def topological_sort_files(py_files: list, src_root: str) -> list: - """对 Python 文件进行拓扑排序,确保依赖模块先被处理""" - # 构建模块名到文件路径的映射 - module_to_file = {} - for filepath in py_files: - rel = os.path.relpath(filepath, src_root) - module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') - module_to_file[module] = filepath - # 也添加顶层模块名 - top_module = module.split('.')[0] - if top_module not in module_to_file: - module_to_file[top_module] = filepath - - # 构建依赖图 - graph = {f: set() for f in py_files} - for filepath in py_files: - deps = get_file_dependencies(filepath, src_root) - for dep in deps: - if dep in module_to_file: - dep_file = module_to_file[dep] - if dep_file != filepath: # 避免自依赖 - graph[filepath].add(dep_file) - - # 拓扑排序 (Kahn's algorithm) - in_degree = {f: 0 for f in py_files} - for f, deps in graph.items(): - for dep in deps: - if dep in in_degree: - in_degree[f] += 1 - - queue = [f for f, degree in in_degree.items() if degree == 0] - sorted_files = [] - - while queue: - # 按字母顺序处理同级别的文件,确保确定性 - queue.sort() - current = queue.pop(0) - sorted_files.append(current) - - for f, deps in graph.items(): - if current in deps: - in_degree[f] -= 1 - if in_degree[f] == 0: - queue.append(f) - - # 如果有环,添加剩余文件 - if len(sorted_files) < len(py_files): - remaining = [f for f in py_files if f not in sorted_files] - sorted_files.extend(remaining) - - return sorted_files - - -class Phase1Generator: - """阶段一:从源文件生成声明接口""" - - def __init__(self, src_root: str, temp_dir: str, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None): - self.src_root = os.path.abspath(src_root) - self.temp_dir = os.path.abspath(temp_dir) - self.include_dirs = include_dirs or [] - self.sha1_map: dict[str, str] = {} - self.include_py_map: dict[str, str] = {} - self.entry_files = entry_files - self.target_triple = target_triple - self.target_datalayout = target_datalayout - os.makedirs(self.temp_dir, exist_ok=True) - - def _get_needed_include_files(self, reachable_source_files: set) -> list: - """从可达源文件收集所有被引用(含传递依赖)的 include 文件""" - include_file_map = {} - for includes_dir in self.include_dirs: - if not os.path.isdir(includes_dir): - continue - for root, dirs, files in os.walk(includes_dir): - dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] - for fname in files: - if fname.endswith('.py') or fname.endswith('.pyi'): - src_path = os.path.join(root, fname) - rel_from_inc = os.path.relpath(src_path, includes_dir) - module_path = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(module_path)[0] - info = (src_path, rel_from_inc, includes_dir) - include_file_map[module_name] = info - top_pkg = module_name.split('.')[0] - if top_pkg not in include_file_map: - include_file_map[top_pkg] = info - - imported_from_src = set() - for src_path in reachable_source_files: - deps = get_file_dependencies(src_path, self.src_root) - imported_from_src.update(deps) - - needed = set() - queue = list(imported_from_src) - while queue: - mod_name = queue.pop(0) - if mod_name in needed: - continue - if mod_name in include_file_map: - needed.add(mod_name) - src_path = include_file_map[mod_name][0] - includes_dir = include_file_map[mod_name][2] - deps = get_file_dependencies(src_path, includes_dir) - for dep in deps: - if dep in include_file_map and dep not in needed: - queue.append(dep) - - needed_infos = [] - for mod_name in sorted(needed): - if mod_name in include_file_map: - info = include_file_map[mod_name] - if info not in needed_infos: - needed_infos.append(info) - - return needed_infos - - def run(self): - """扫描源目录,只处理入口文件可达的 .py 文件(导入遍历)""" - if self.entry_files: - py_files = list(self.entry_files) - else: - main_py = os.path.join(self.src_root, 'main.py') - if os.path.exists(main_py): - py_files = [main_py] - else: - py_files = [] - for root, dirs, files in os.walk(self.src_root): - dirs[:] = [d for d in dirs if d not in ('__pycache__',)] - for file in files: - if file.endswith('.py'): - py_files.append(os.path.join(root, file)) - - if not py_files: - print("[阶段一] 未找到入口文件或源文件") - return - - if self.entry_files: - reachable = find_reachable_files_from_entries(self.src_root, py_files) - else: - reachable = find_reachable_files_from_entries(self.src_root, py_files) - - print(f"[阶段一] 找到 {len(reachable)} 个可达源文件(从入口遍历)") - - for i, src_path in enumerate(sorted(reachable), 1): - rel = os.path.relpath(src_path, self.src_root) - print(f"[{i}/{len(reachable)}] 生成签名: {rel}") - try: - self._process_file_pyi(src_path, rel) - except Exception as e: - print(f" [错误] {e}") - traceback.print_exc() - - needed_includes = self._get_needed_include_files(reachable) - self._process_include_py_files_pyi(needed_includes) - - struct_names, enum_names, struct_sha1_map, exception_names = self._build_struct_registry() - print(f"\n[阶段一] 结构体注册表: {len(struct_names)} 个类型, {len(enum_names)} 个枚举") - for name in sorted(struct_names): - print(f" {name}") - - for i, src_path in enumerate(sorted(reachable), 1): - rel = os.path.relpath(src_path, self.src_root) - try: - self._process_file_stub(src_path, rel, struct_names, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) - except Exception as e: - print(f" [错误] {e}") - traceback.print_exc() - - self._process_include_py_files_stub(struct_names, needed_includes, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) - - print(f"\n[阶段一完成] 声明接口生成到: {self.temp_dir}") - print(f"SHA1 映射表 ({len(self.sha1_map)} 个文件):") - for sha1, rel in sorted(self.sha1_map.items()): - print(f" {sha1} -> {rel}") - - def _collect_include_py_files(self): - include_py_files = [] - for includes_dir in self.include_dirs: - if not os.path.isdir(includes_dir): - continue - for root, dirs, files in os.walk(includes_dir): - dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] - for fname in files: - if fname.endswith('.py') or fname.endswith('.pyi'): - src_path = os.path.join(root, fname) - rel_from_inc = os.path.relpath(src_path, includes_dir) - include_py_files.append((src_path, rel_from_inc, includes_dir)) - return include_py_files - - def _process_include_py_files_pyi(self, needed_includes: list = None): - if needed_includes is not None: - include_py_files = needed_includes - else: - include_py_files = self._collect_include_py_files() - if not include_py_files: - return - print(f"\n[阶段一-includes] 处理 {len(include_py_files)} 个被引用的 Python 库文件") - for src_path, rel_from_inc, includes_dir in include_py_files: - module_path = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(module_path)[0] - try: - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - sha1 = compute_sha1(content) - self.sha1_map[sha1] = f"includes/{rel_from_inc}" - top_module = rel_from_inc.split(os.sep)[0].split('/')[0] - if top_module not in self.include_py_map: - self.include_py_map[top_module] = sha1 - self.include_py_map[module_name] = sha1 - - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") - if os.path.isfile(sig_path): - print(f" 缓存命中: {rel_from_inc} -> {sha1}.pyi") - continue - - sig_content = PythonToStubConverter.convert(content, module_name) - with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(sig_content) - print(f" 生成签名: {rel_from_inc} -> {sha1}.pyi") - except Exception as e: - print(f" [错误] {rel_from_inc}: {e}") - - def _collect_typedef_map(self): - import ast as _ast - typedef_map = {} - if not os.path.isdir(self.temp_dir): - return typedef_map - for fname in os.listdir(self.temp_dir): - if not fname.endswith('.pyi'): - continue - pyi_path = os.path.join(self.temp_dir, fname) - try: - with open(pyi_path, 'r', encoding='utf-8') as f: - content = f.read() - tree = _ast.parse(content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): - var_name = node.target.id - is_typedef = False - if isinstance(node.annotation, _ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': - is_typedef = True - elif isinstance(node.annotation, _ast.Name) and node.annotation.id == 'CTypedef': - is_typedef = True - elif isinstance(node.annotation, _ast.BinOp) and isinstance(node.annotation.left, _ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': - is_typedef = True - if is_typedef and node.value and var_name not in typedef_map: - typedef_map[var_name] = node.value - except Exception: - pass - return typedef_map - - def _process_include_py_files_stub(self, struct_names: set, needed_includes: list = None, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): - if needed_includes is not None: - include_py_files = needed_includes - else: - include_py_files = self._collect_include_py_files() - if not include_py_files: - return - typedef_map = self._collect_typedef_map() - for src_path, rel_from_inc, includes_dir in include_py_files: - module_path = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(module_path)[0] - try: - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - sha1 = compute_sha1(content) - - stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") - if os.path.isfile(stub_path): - print(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll") - continue - - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") - with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() - - self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - print(f" 生成声明: {rel_from_inc} -> {sha1}.stub.ll") - except Exception as e: - print(f" [错误] {rel_from_inc}: {e}") - - def _process_file_pyi(self, src_path: str, rel_path: str): - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - - sha1 = compute_sha1(content) - self.sha1_map[sha1] = rel_path - - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") - if os.path.isfile(sig_path): - print(f" -> {sha1}.pyi (缓存)") - return - - module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - sig_content = PythonToStubConverter.convert(content, module_name) - with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(sig_content) - print(f" -> {sha1}.pyi (签名)") - - def _process_file_stub(self, src_path: str, rel_path: str, struct_names: set, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - - sha1 = compute_sha1(content) - stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") - if os.path.isfile(stub_path): - print(f" -> {sha1}.stub.ll (缓存)") - return - - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") - with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() - - typedef_map = self._collect_typedef_map() - self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - print(f" -> {sha1}.stub.ll (声明)") - - def _build_struct_registry(self): - struct_names = set() - enum_names = set() - exception_names = set() - struct_sha1_map = {} - valid_sha1_keys = set(self.sha1_map.keys()) - for fname in os.listdir(self.temp_dir): - if not fname.endswith('.pyi'): - continue - sha1_key = fname.replace('.pyi', '') - if sha1_key not in valid_sha1_keys: - continue - pyi_path = os.path.join(self.temp_dir, fname) - try: - with open(pyi_path, 'r', encoding='utf-8') as f: - content = f.read() - tree = ast.parse(content) - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.ClassDef): - is_enum = False - is_exception = False - if node.bases: - for base in node.bases: - if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): - if base.attr in ('CEnum', 'Enum'): - is_enum = True - break - elif base.attr == 'Exception' or base.attr in exception_names: - is_exception = True - break - elif isinstance(base, ast.Name) and hasattr(base, 'id'): - if base.id in ('CEnum', 'Enum'): - is_enum = True - break - elif base.id == 'Exception' or base.id in exception_names: - is_exception = True - break - if is_enum: - enum_names.add(node.name) - elif is_exception: - exception_names.add(node.name) - else: - struct_names.add(node.name) - struct_sha1_map[node.name] = sha1_key - except Exception: - pass - return struct_names, enum_names, struct_sha1_map, exception_names - - def _generate_decl_ll(self, pyi_content: str, ll_path: str, src_path: str, struct_names: set = None, enum_names: set = None, module_sha1: str = None, struct_sha1_map: dict = None, exception_names: set = None, typedef_map: dict = None): - try: - decl_gen = DeclarationGenerator(struct_names=struct_names, enum_names=enum_names, module_sha1=module_sha1, target_triple=self.target_triple, target_datalayout=self.target_datalayout, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - decl_ll = decl_gen.generate(pyi_content, src_path) - with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(decl_ll) - except Exception as e: - print(f" [警告] .ll 声明生成失败: {e}") - with open(ll_path, 'w', encoding='utf-8') as f: - f.write(f"; declaration for {os.path.basename(src_path)}\n; error: {e}\n") - - -class DeclarationGenerator: - """从 .pyi AST 生成纯 LLVM IR 声明(不使用字符串操作)""" - - def __init__(self, struct_names=None, enum_names=None, module_sha1=None, target_triple=None, target_datalayout=None, struct_sha1_map=None, exception_names=None, typedef_map=None): - import llvmlite.ir as ir - self.ir = ir - self.module = None - self.builder = None - self._define_constants = {} - self.struct_names = struct_names or set() - self.enum_names = enum_names or set() - self.module_sha1 = module_sha1 - self.struct_sha1_map = struct_sha1_map or {} - self.exception_names = exception_names or set() - self.target_triple = target_triple or "x86_64-none-elf" - self.target_datalayout = target_datalayout or "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - self.typedef_map = typedef_map or {} - t.configure_platform(self.target_triple) - - def generate(self, pyi_content: str, src_path: str) -> str: - import ast - tree = ast.parse(pyi_content) - - self._define_constants = {} - self._pyi_tree = tree - global_typedef_map = self.typedef_map - self.typedef_map = {} - if global_typedef_map: - self.typedef_map.update(global_typedef_map) - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - var_name = node.target.id - if node.value and isinstance(node.value, ast.Constant): - self._define_constants[var_name] = node.value.value - elif node.value and isinstance(node.value, ast.Name): - self._define_constants[var_name] = node.value.id - is_typedef = False - if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': - is_typedef = True - elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': - is_typedef = True - elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': - is_typedef = True - if is_typedef: - if node.value: - self.typedef_map[var_name] = node.value - elif isinstance(node.annotation, ast.BinOp) and node.annotation.right: - self.typedef_map[var_name] = node.annotation.right - - lines = [] - lines.append('; ModuleID = "transpyc_decl"') - lines.append(f'target triple = "{self.target_triple}"') - lines.append(f'target datalayout = "{self.target_datalayout}"') - lines.append('') - - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.FunctionDef): - if hasattr(node, 'type_params') and node.type_params: - continue - decl = self._generate_func_decl(node) - if decl: - lines.append(decl) - elif isinstance(node, ast.AnnAssign): - decl = self._generate_global_decl(node) - if decl: - lines.append(decl) - elif isinstance(node, ast.Assign): - decl = self._generate_global_assign_decl(node) - if decl: - lines.append(decl) - elif isinstance(node, ast.ClassDef): - if hasattr(node, 'type_params') and node.type_params: - continue - decls = self._generate_class_decl(node) - lines.extend(decls) - - return '\n'.join(lines) - - def _generate_func_decl(self, node: ast.FunctionDef) -> str: - """生成函数声明""" - func_name = node.name - is_export = self._is_export_func(node) - if self.module_sha1 and not is_export: - func_name = f"{self.module_sha1}.{func_name}" - CReturnTypes = [] - if node.decorator_list: - for decorator in node.decorator_list: - if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): - if decorator.func.attr == 'CReturn': - for arg in decorator.args: - CReturnTypes.append(arg) - if node.returns: - if isinstance(node.returns, ast.Subscript) and isinstance(node.returns.value, ast.Name) and node.returns.value.id == 'tuple': - slice_node = node.returns.slice - if isinstance(slice_node, ast.Tuple): - for elt in slice_node.elts: - CReturnTypes.append(elt) - else: - CReturnTypes.append(slice_node) - if CReturnTypes: - elem_types = [self._get_type_str(rt, embedded=True) for rt in CReturnTypes] - ret_type = '{ ' + ', '.join(elem_types) + ' }' - else: - ret_type = self._get_type_str(node.returns) - if not ret_type or ret_type == 'void': - ret_type = 'void' - elif ret_type == 'i8*': - if node.returns is None: - ret_type = 'void' - - params = [] - for arg in node.args.args: - if arg.annotation: - arg_type = self._get_type_str(arg.annotation) - else: - arg_type = 'i8*' - if arg_type and arg_type != 'void': - params.append(arg_type) - - param_str = ', '.join(params) if params else '' - if node.args.vararg: - param_str = param_str + ', ...' if param_str else '...' - if func_name[0].isdigit(): - return f'declare {ret_type} @"{func_name}"({param_str})' - return f'declare {ret_type} @{func_name}({param_str})' - - def _is_export_func(self, node: ast.FunctionDef) -> bool: - """检查函数是否标记为 CExport""" - if not node.returns: - return False - return self._check_annotation_for_export(node.returns) - - def _check_annotation_for_export(self, annotation) -> bool: - """递归检查类型注解中是否包含 CExport 或 t.State""" - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'State'): - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return self._check_annotation_for_export(annotation.left) or self._check_annotation_for_export(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id in ('CExport', 'State') - return False - - def _generate_global_decl(self, node: ast.AnnAssign) -> str: - """生成全局变量声明""" - if not isinstance(node.target, ast.Name): - return None - var_name = node.target.id - if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CDefine': - return None - if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': - return None - if isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': - return None - if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': - return None - if isinstance(node.annotation, ast.List): - for elt in node.annotation.elts: - if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'): - return None - if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Attribute) and isinstance(elt.value.value, ast.Name) and elt.value.value.id == 't' and elt.value.attr == 'Callable': - return None - var_type = self._get_type_str(node.annotation) - if var_type.startswith('[0 x ') and node.value and isinstance(node.value, ast.List): - elem_type = var_type[5:-1] - actual_count = len(node.value.elts) - if actual_count > 0: - var_type = f'[{actual_count} x {elem_type}]' - return f'@{var_name} = external global {var_type}' - - def _generate_global_assign_decl(self, node: ast.Assign) -> str: - """从无类型标注赋值推断并生成全局变量声明""" - if not node.targets or not isinstance(node.targets[0], ast.Name): - return None - var_name = node.targets[0].id - var_type = self._infer_type(node.value) - if var_type: - return f'@{var_name} = external global {var_type}' - return None - - def _generate_class_decl(self, node: ast.ClassDef) -> List[str]: - """生成结构体/类声明""" - decls = [] - class_name = node.name - is_enum = False - is_exception = False - if node.bases: - for base in node.bases: - if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): - if base.attr == 'CEnum' or base.attr == 'Enum': - is_enum = True - break - elif base.attr == 'Exception' or base.attr in self.exception_names: - is_exception = True - break - elif isinstance(base, ast.Name) and hasattr(base, 'id'): - if base.id == 'CEnum' or base.id == 'Enum': - is_enum = True - break - elif base.id == 'Exception' or base.id in self.exception_names: - is_exception = True - break - if is_exception: - return decls - if is_enum: - enum_values = {} - next_value = 0 - for item in node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - var_name = item.target.id - if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): - enum_values[var_name] = item.value.value - else: - enum_values[var_name] = next_value - next_value += 1 - elif isinstance(item, ast.Assign) and len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): - var_name = item.targets[0].id - if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): - enum_values[var_name] = item.value.value - next_value = item.value.value + 1 - else: - enum_values[var_name] = next_value - next_value += 1 - for var_name, value in enum_values.items(): - decls.append(f'@__config_{class_name}_{var_name} = external global i32') - return decls - member_types = [] - has_bitfield = False - total_bits = 0 - has_methods = any(isinstance(item, ast.FunctionDef) for item in node.body) - is_cvtable = False - is_cpython_object = False - if hasattr(node, 'decorator_list') and node.decorator_list: - for decorator in node.decorator_list: - if isinstance(decorator, ast.Attribute): - if getattr(decorator.value, 'id', None) == 't': - if decorator.attr == 'CVTable': - is_cvtable = True - elif decorator.attr == 'Object': - is_cpython_object = True - elif isinstance(decorator, ast.Name): - if decorator.id == 'CVTable': - is_cvtable = True - elif decorator.id == 'Object': - is_cpython_object = True - if has_methods and not is_cpython_object: - is_cpython_object = True - has_parent_class = False - for base in node.bases: - base_name = None - if isinstance(base, ast.Attribute): - base_name = base.attr - elif isinstance(base, ast.Name): - base_name = base.id - elif isinstance(base, ast.Subscript): - if isinstance(base.value, ast.Attribute): - base_name = base.value.attr - elif isinstance(base.value, ast.Name): - base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): - has_parent_class = True - break - if has_parent_class and not is_cvtable: - is_cvtable = True - base_has_vtable = False - for base in node.bases: - base_name = None - if isinstance(base, ast.Attribute): - base_name = base.attr - elif isinstance(base, ast.Name): - base_name = base.id - elif isinstance(base, ast.Subscript): - if isinstance(base.value, ast.Attribute): - base_name = base.value.attr - elif isinstance(base.value, ast.Name): - base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): - for n in ast.iter_child_nodes(self._pyi_tree): - if isinstance(n, ast.ClassDef) and n.name == base_name: - if hasattr(n, 'decorator_list') and n.decorator_list: - for dec in n.decorator_list: - if isinstance(dec, ast.Attribute) and getattr(dec.value, 'id', None) == 't' and dec.attr == 'CVTable': - base_has_vtable = True - elif isinstance(dec, ast.Name) and dec.id == 'CVTable': - base_has_vtable = True - break - if base_has_vtable: - break - if has_methods and is_cvtable and not base_has_vtable: - member_types.append('i8*') - seen_member_names = set() - for base in node.bases: - base_name = None - if isinstance(base, ast.Attribute): - base_name = base.attr - elif isinstance(base, ast.Name): - base_name = base.id - elif isinstance(base, ast.Subscript): - if isinstance(base.value, ast.Attribute): - base_name = base.value.attr - elif isinstance(base.value, ast.Name): - base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): - base_member_types, base_seen = self._get_inherited_members(base_name) - for mt in base_member_types: - member_types.append(mt) - seen_member_names.update(base_seen) - for item in node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - seen_member_names.add(item.target.id) - init_members = [] - for item in node.body: - if isinstance(item, ast.FunctionDef) and item.name == '__init__': - for stmt in item.body: - if (isinstance(stmt, ast.AnnAssign) - and isinstance(stmt.target, ast.Attribute) - and isinstance(stmt.target.value, ast.Name) - and stmt.target.value.id == 'self'): - init_members.append(stmt) - untyped_self_members = [] - for m_name in [m.attr for m in init_members if isinstance(m.target, ast.Attribute)]: - seen_member_names.add(m_name) - for item in node.body: - if isinstance(item, ast.FunctionDef): - if hasattr(item, 'type_params') and item.type_params: - continue - for stmt in item.body: - if (isinstance(stmt, ast.Assign) - and len(stmt.targets) == 1 - and isinstance(stmt.targets[0], ast.Attribute) - and isinstance(stmt.targets[0].value, ast.Name) - and stmt.targets[0].value.id == 'self'): - attr_name = stmt.targets[0].attr - if attr_name not in seen_member_names: - seen_member_names.add(attr_name) - untyped_self_members.append(stmt) - for item in list(node.body) + init_members + untyped_self_members: - if isinstance(item, ast.AnnAssign): - bit_width = self._get_bitfield_width(item.annotation) - if bit_width is not None: - has_bitfield = True - total_bits += bit_width - else: - var_type = self._get_type_str(item.annotation, embedded=True) - if (isinstance(item.annotation, ast.Subscript) - and isinstance(item.annotation.value, ast.Name) - and item.annotation.value.id == 'list'): - slice_node = item.annotation.slice - is_dynamic = False - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - count_node = slice_node.elts[1] - if isinstance(count_node, ast.Constant) and count_node.value is None: - is_dynamic = True - elif not (isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0): - if not isinstance(count_node, (ast.Name, ast.BinOp)): - is_dynamic = True - elif not isinstance(slice_node, ast.Tuple): - is_dynamic = True - if is_dynamic: - elem_type = self._get_type_str(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0], embedded=True) - init_len = 0 - if isinstance(item.value, ast.List): - init_len = len(item.value.elts) - elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): - init_len = len(item.value.value) + 1 - var_type = f'[{init_len} x {elem_type}]' - member_types.append(var_type) - elif isinstance(item, ast.Assign): - if (len(item.targets) == 1 - and isinstance(item.targets[0], ast.Attribute) - and isinstance(item.targets[0].value, ast.Name) - and item.targets[0].value.id == 'self'): - attr_name = item.targets[0].attr - if attr_name in seen_member_names: - continue - InferredType = 'i32' - if item.value and isinstance(item.value, ast.Constant): - if isinstance(item.value.value, float): - InferredType = 'float' - elif isinstance(item.value.value, bool): - InferredType = 'i8' - elif isinstance(item.value.value, str): - InferredType = 'i8*' - member_types.append(InferredType) - else: - member_types.append('i32') - if has_bitfield: - if total_bits <= 8: - member_types.insert(0, 'i8') - elif total_bits <= 16: - member_types.insert(0, 'i16') - elif total_bits <= 32: - member_types.insert(0, 'i32') - else: - member_types.insert(0, 'i64') - struct_type_name = f'%"{self.module_sha1}.{class_name}"' if self.module_sha1 else f'%struct.{class_name}' - struct_decl = f'{struct_type_name} = type {{ {", ".join(member_types)} }}' - decls.append(struct_decl) - if is_cpython_object or is_cvtable: - new_func_name = f'{class_name}.__before_init__' - if self.module_sha1: - new_func_name = f"{self.module_sha1}.{new_func_name}" - if new_func_name[0].isdigit(): - new_func_decl = f'declare void @"{new_func_name}"({struct_type_name}*)' - else: - new_func_decl = f'declare void @{new_func_name}({struct_type_name}*)' - decls.append(new_func_decl) - for item in node.body: - if isinstance(item, ast.FunctionDef): - if hasattr(item, 'type_params') and item.type_params: - continue - method_name = f'{class_name}.{item.name}' - if self.module_sha1: - method_name = f"{self.module_sha1}.{method_name}" - ret_type = self._get_type_str(item.returns) if item.returns else 'void' - if not ret_type: - ret_type = 'void' - params = [] - for arg_idx, arg in enumerate(item.args.args): - if arg.annotation: - arg_type = self._get_type_str(arg.annotation) - elif arg_idx == 0 and arg.arg == 'self': - arg_type = f'{struct_type_name}*' - else: - arg_type = 'i8*' - params.append(arg_type) - param_str = ', '.join(params) if params else '' - if method_name[0].isdigit(): - decls.append(f'declare {ret_type} @"{method_name}"({param_str})') - else: - decls.append(f'declare {ret_type} @{method_name}({param_str})') - return decls - - def _get_inherited_members(self, base_name: str): - import ast - member_types = [] - seen_names = set() - if not hasattr(self, '_pyi_tree') or self._pyi_tree is None: - return member_types, seen_names - base_node = None - for node in ast.iter_child_nodes(self._pyi_tree): - if isinstance(node, ast.ClassDef) and node.name == base_name: - base_node = node - break - if base_node is None: - return member_types, seen_names - base_decls = self._generate_class_decl(base_node) - for decl in base_decls: - if '= type {' in decl: - type_body = decl.split('= type {')[1].rstrip('}').strip() - if type_body: - for t in type_body.split(','): - t = t.strip() - if t: - member_types.append(t) - break - for item in base_node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - seen_names.add(item.target.id) - elif isinstance(item, ast.Assign) and len(item.targets) == 1: - if isinstance(item.targets[0], ast.Attribute) and isinstance(item.targets[0].value, ast.Name) and item.targets[0].value.id == 'self': - seen_names.add(item.targets[0].attr) - for item in base_node.body: - if isinstance(item, ast.FunctionDef) and item.name == '__init__': - for stmt in item.body: - if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Attribute) and isinstance(stmt.target.value, ast.Name) and stmt.target.value.id == 'self': - seen_names.add(stmt.target.attr) - elif isinstance(stmt, ast.Assign) and len(stmt.targets) == 1 and isinstance(stmt.targets[0], ast.Attribute) and isinstance(stmt.targets[0].value, ast.Name) and stmt.targets[0].value.id == 'self': - seen_names.add(stmt.targets[0].attr) - return member_types, seen_names - - @staticmethod - def _ctype_name_to_llvm(name: str) -> str: - """根据 CType 元属性自动推导 LLVM IR 类型 - - 通过 CTypeRegistry.NameToLLVM 查询,利用 CType 的 - position/IsSigned/Size 元属性自动推导,无需手动映射表。 - """ - from lib.includes.t import CTypeRegistry - result = CTypeRegistry.NameToLLVM(name) - return result - - def _get_type_str(self, annotation: ast.AST, embedded: bool = False) -> str: - import ast - from lib.includes.t import CTypeRegistry - if annotation is None: - return 'i8*' - - non_struct_types = {'list', 'dict', 'tuple', 'set', 'array'} - - if isinstance(annotation, ast.Name): - if annotation.id == 'None': - return 'void' - if annotation.id in ('str', 'bytes'): - return 'i8*' - llvm_type = CTypeRegistry.NameToLLVM(annotation.id) - if llvm_type is not None: - return llvm_type - resolved = CTypeRegistry.ResolveName(annotation.id) - if resolved is not None: - ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) - if ptr_level > 0: - if base == 'void': - return 'i8*' - if '*' in base: - return base - return f'{base}*' - return base - if annotation.id in non_struct_types: - return 'i32' - if annotation.id in self.enum_names: - return 'i32' - if annotation.id in self.struct_names: - sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) - sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' - if embedded: - return sname - else: - return f'{sname}*' - if annotation.id in self.typedef_map: - resolved = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded) - return resolved - sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) - sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' - return f'{sname}*' - elif isinstance(annotation, ast.Attribute): - attr_name = annotation.attr if hasattr(annotation, 'attr') else '' - module_name = '' - if hasattr(annotation, 'value'): - if isinstance(annotation.value, ast.Name): - module_name = annotation.value.id - elif isinstance(annotation.value, ast.Attribute) and hasattr(annotation.value, 'attr'): - module_name = annotation.value.attr - if (module_name == 't' and attr_name == 'State') or attr_name == 'State': - return '' - if (module_name == 't' and attr_name == 'Callable') or attr_name == 'Callable': - return 'i8*' - llvm_type = CTypeRegistry.NameToLLVM(attr_name) - if llvm_type is not None: - return llvm_type - resolved = CTypeRegistry.ResolveName(attr_name) - if resolved is not None: - ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) - if ptr_level > 0: - if base == 'void': - return 'i8*' - if '*' in base: - return base - return f'{base}*' - return base - if attr_name in self.typedef_map: - return self._get_type_str(self.typedef_map[attr_name], embedded=embedded) - if attr_name in self.enum_names: - return 'i32' - if attr_name in self.struct_names: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' - if embedded: - return sname - else: - return f'{sname}*' - if attr_name and attr_name[0].isupper() and attr_name not in non_struct_types: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' - return f'{sname}*' - if attr_name and attr_name not in non_struct_types: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' - return f'{sname}*' - return 'i32' - elif isinstance(annotation, ast.BinOp): - left_type = self._get_type_str(annotation.left, embedded=embedded) - right_type = self._get_type_str(annotation.right, embedded=embedded) - if left_type in ('', 'void'): - return right_type if right_type not in ('', 'void') else (left_type or right_type) - if right_type in ('', 'void'): - return left_type - if '*' in left_type: - return left_type - if '*' in right_type: - if right_type == 'i8*': - return self._type_to_llvm_ptr(left_type) - return right_type - return left_type - elif isinstance(annotation, ast.Subscript): - base = self._get_type_str(annotation.value) - if base == 'i8*' and isinstance(annotation.slice, ast.Constant): - return f'[{self._get_const_int(annotation.slice)} x i8]' - if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): - return f'[{annotation.slice.value} x {base}]' - if isinstance(annotation.value, ast.Name) and annotation.value.id == 'list': - slice_node = annotation.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type = self._get_type_str(slice_node.elts[0], embedded=True) - count_node = slice_node.elts[1] - array_count = self._get_const_int(count_node) - if array_count > 0: - return f'[{array_count} x {elem_type}]' - else: - return f'[0 x {elem_type}]' - elem_type = self._get_type_str(slice_node, embedded=True) - return f'[0 x {elem_type}]' - if isinstance(annotation.value, ast.Name) and annotation.value.id == 'tuple': - slice_node = annotation.slice - if isinstance(slice_node, ast.Tuple): - elem_types = [self._get_type_str(e, embedded=True) for e in slice_node.elts] - else: - elem_types = [self._get_type_str(slice_node, embedded=True)] - return '{ ' + ', '.join(elem_types) + ' }' - return f'{base}' - elif isinstance(annotation, ast.Constant): - if annotation.value is None: - return 'void' - if isinstance(annotation.value, int): - return 'i32' - if isinstance(annotation.value, str): - type_name = annotation.value - if type_name in self.enum_names: - return 'i32' - if type_name in self.struct_names: - sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) - sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' - if embedded: - return sname - else: - return f'{sname}*' - llvm_type = CTypeRegistry.NameToLLVM(type_name) - if llvm_type is not None: - return llvm_type - resolved = CTypeRegistry.ResolveName(type_name) - if resolved is not None: - ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) - if ptr_level > 0: - if base == 'void': - return 'i8*' - if '*' in base: - return base - return f'{base}*' - return base - sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) - sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' - return f'{sname}*' - return 'i8*' - elif isinstance(annotation, ast.Call): - if isinstance(annotation.func, ast.Name) and annotation.func.id == 'callable': - return 'i8*' - if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Callable': - return 'i8*' - return 'i32' - - def _type_to_llvm_ptr(self, type_str: str) -> str: - if type_str.startswith('%struct.') and not type_str.endswith('*'): - return type_str + '*' - if type_str.startswith('%') and not type_str.endswith('*'): - return type_str + '*' - if type_str.endswith('*'): - return type_str - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(type_str) - if resolved is not None: - ctype_cls, ptr_level = resolved - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str: - return f'{llvm_str}{"*" * (ptr_level + 1)}' - cnameres = CTypeRegistry.CNameToClass(type_str) - if cnameres is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) - if llvm_str: - return f'{llvm_str}*' - return f'{type_str}*' - - def _infer_type(self, value: ast.AST) -> str: - """从值推断类型""" - import ast - if isinstance(value, ast.Constant): - if isinstance(value.value, int): - return 'i32' - elif isinstance(value.value, float): - return 'double' - elif isinstance(value.value, str): - return 'i8*' - elif isinstance(value.value, bool): - return 'i8' - elif isinstance(value, ast.List): - return 'i8*' - elif isinstance(value, ast.Dict): - return 'i8*' - elif isinstance(value, ast.Name): - return 'i32' - elif isinstance(value, ast.BinOp): - return self._infer_type(value.left) - elif isinstance(value, ast.Call): - return 'i8*' - return 'i32' - - def _get_bitfield_width(self, annotation: ast.AST): - import ast - if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - right_width = self._get_bitfield_width(annotation.right) - if right_width is not None: - return right_width - return self._get_bitfield_width(annotation.left) - if isinstance(annotation, ast.Call): - if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Bit': - if annotation.args: - arg = annotation.args[0] - if isinstance(arg, ast.Constant) and isinstance(arg.value, int): - return arg.value - if isinstance(annotation, ast.Subscript): - if isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'Bit': - if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): - return annotation.slice.value - return None - - def _get_const_int(self, node: ast.AST) -> int: - """获取常量整数值,支持符号常量和简单表达式""" - import ast - if isinstance(node, ast.Constant) and isinstance(node.value, int): - return node.value - if isinstance(node, ast.Name): - if node.id in self._define_constants: - val = self._define_constants[node.id] - if isinstance(val, int): - return val - if isinstance(node, ast.BinOp): - left_val = self._get_const_int(node.left) - right_val = self._get_const_int(node.right) - if left_val and right_val: - if isinstance(node.op, ast.Add): - return left_val + right_val - if isinstance(node.op, ast.Sub): - return left_val - right_val - if isinstance(node.op, ast.Mult): - return left_val * right_val - if isinstance(node.op, ast.Div): - return left_val // right_val - if isinstance(node.op, ast.FloorDiv): - return left_val // right_val - return 0 - - -def _parallel_translate_worker(src_path, out_path, src_root, temp_dir, output_dir, - include_dirs, triple, datalayout, sha1_map, sig_files, - stub_files, include_py_map, slice_level, - shared_sym_pickle_path, struct_sha1_map): - try: - import pickle - from Projectrans import Phase2Translator, compute_sha1 - trans = Phase2Translator(src_root, temp_dir, output_dir, - compile_cmd='llc', include_dirs=include_dirs, - target_triple=triple, target_datalayout=datalayout) - trans.sha1_map = sha1_map - trans.sig_files = sig_files - trans.stub_files = stub_files - trans.include_py_map = include_py_map - trans.slice_level = slice_level - trans.struct_sha1_map = struct_sha1_map - - if shared_sym_pickle_path and os.path.exists(shared_sym_pickle_path): - with open(shared_sym_pickle_path, 'rb') as f: - shared_data = pickle.load(f) - trans._shared_symbol_table = shared_data['symbol_table'] - trans._shared_source_module_sig_files = shared_data['source_module_sig_files'] - trans._shared_all_dc = shared_data['all_dc'] - trans._shared_export_extern_funcs = shared_data['export_extern_funcs'] - trans.inline_func_symbols = shared_data['inline_func_symbols'] - trans.function_default_args = shared_data['function_default_args'] - trans._shared_generic_class_templates = shared_data.get('generic_class_templates', {}) - else: - trans._precollect_inline_symbols() - trans._build_shared_symbol_data() - - trans._translate_file(src_path, out_path) - return ('ok', src_path, '') - except Exception as e: - import traceback - return ('error', src_path, f'{e}\n{traceback.format_exc(limit=50)}') - - -class Phase2Translator: - """阶段二:使用声明接口翻译源文件""" - - INCLUDE_LIB_EXTENSIONS = ('.dll', '.ll', '.so', '.o', '.a', '.lib') - INCLUDE_SRC_EXTENSIONS = ('.c', '.cpp', '.cc', '.cxx', '.m', '.mm') - INCLUDE_DIRS = [ - os.path.join(os.path.dirname(os.path.abspath(__file__)), 'includes'), - r"d:\Users\TermiNexus\Desktop\TransPyC\includes", - ] - - def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list = None, linker_cmd: str = None, linker_flags: list = None, linker_output: str = None, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None): - self.src_root = os.path.abspath(src_root) - self.temp_dir = os.path.abspath(temp_dir) - self.output_dir = os.path.abspath(output_dir) - self.compile_cmd = compile_cmd - self.compile_flags = compile_flags or ['-filetype=obj'] - self.triple = target_triple - self.datalayout = target_datalayout - if not self.triple: - for i, flag in enumerate(self.compile_flags): - if flag.startswith('-mtriple='): - self.triple = flag[len('-mtriple='):] - elif flag == '-mtriple' and i + 1 < len(self.compile_flags): - self.triple = self.compile_flags[i + 1] - self.linker_cmd = linker_cmd - self.linker_flags = linker_flags or [] - self.linker_output = linker_output - self.slice_level = 3 - self.sha1_map: dict[str, str] = {} - self.sig_files: dict[str, str] = {} - self.stub_files: dict[str, str] = {} - self.include_py_map: dict[str, str] = {} - self.used_includes: set = set() - self._last_error_stack = None - self.function_default_args: dict = {} - self.inline_func_symbols: dict = {} - self.extra_link_files: list = [] - self.extra_compile_files: list = [] - self.extra_py_files: list = [] - self._include_sha1s: set = set() - self.entry_files = entry_files - self._shared_symbol_table = None - self._shared_source_module_sig_files = {} - self._shared_all_dc = {} - self._shared_export_extern_funcs = set() - self._stub_decls_cache = {} - default_dirs = [d for d in self.INCLUDE_DIRS if os.path.isdir(d)] - if include_dirs: - seen = set() - self.include_dirs = [] - for d in list(include_dirs) + default_dirs: - d = os.path.abspath(d) - if d not in seen and os.path.isdir(d): - self.include_dirs.append(d) - seen.add(d) - else: - self.include_dirs = default_dirs - self._load_sha1_map() - - def _load_sha1_map(self): - """从 temp_dir 加载 SHA1 映射、签名文件和 stub 声明文件列表""" - if not os.path.exists(self.temp_dir): - print(f"[错误] 声明目录不存在: {self.temp_dir}") - return - - for fname in os.listdir(self.temp_dir): - fpath = os.path.join(self.temp_dir, fname) - if fname.startswith('_'): - continue - if fname.endswith('.pyi'): - sha1 = fname[:-4] - self.sig_files[sha1] = fpath - elif fname.endswith('.stub.ll'): - sha1 = fname[:-8] - self.stub_files[sha1] = fpath - - sha1_file_path = os.path.join(self.temp_dir, '_sha1_map.txt') - if os.path.exists(sha1_file_path): - with open(sha1_file_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if ':' in line: - sha1, rel = line.split(':', 1) - self.sha1_map[sha1] = rel - if rel.startswith('includes/'): - module_name = os.path.splitext(os.path.basename(rel))[0] - self.include_py_map[module_name] = sha1 - else: - for sha1, stub_path in self.stub_files.items(): - self.sha1_map[sha1] = sha1 - - def _build_struct_sha1_map(self): - struct_sha1_map = {} - valid_sha1_keys = set(self.sha1_map.keys()) - for fname in os.listdir(self.temp_dir): - if not fname.endswith('.pyi'): - continue - sha1_key = fname.replace('.pyi', '') - if sha1_key not in valid_sha1_keys: - continue - pyi_path = os.path.join(self.temp_dir, fname) - try: - with open(pyi_path, 'r', encoding='utf-8') as f: - tree = ast.parse(f.read()) - except Exception: - continue - for node in ast.walk(tree): - if isinstance(node, ast.ClassDef): - struct_sha1_map[node.name] = sha1_key - return struct_sha1_map - - def run(self): - """扫描源目录,翻译并生成 .ll 含代码文件(导入遍历)""" - if self.entry_files: - py_files = list(self.entry_files) - else: - main_py = os.path.join(self.src_root, 'main.py') - if os.path.exists(main_py): - py_files = [main_py] - else: - py_files = [] - for root, dirs, files in os.walk(self.src_root): - dirs[:] = [d for d in dirs if d not in ('__pycache__',)] - for file in files: - if file.endswith('.py'): - py_files.append(os.path.join(root, file)) - - if not py_files: - print("[阶段二] 未找到入口文件或源文件") - return - - reachable = find_reachable_files_from_entries(self.src_root, py_files) - py_files = list(reachable) - - py_files = topological_sort_files(py_files, self.src_root) - - print(f"[阶段二] 找到 {len(py_files)} 个可达源文件(已按依赖排序)") - print("[阶段二] 处理顺序:") - for i, f in enumerate(py_files[:10], 1): - rel = os.path.relpath(f, self.src_root) - print(f" {i}. {rel}") - os.makedirs(self.output_dir, exist_ok=True) - - valid_sha1s = set(self.sha1_map.keys()) - old_stub_count = len(self.stub_files) - old_sig_count = len(self.sig_files) - self.stub_files = {k: v for k, v in self.stub_files.items() if k in valid_sha1s} - self.sig_files = {k: v for k, v in self.sig_files.items() if k in valid_sha1s} - if old_stub_count != len(self.stub_files) or old_sig_count != len(self.sig_files): - print(f"[阶段二] 过滤旧文件: stub {old_stub_count}->{len(self.stub_files)}, sig {old_sig_count}->{len(self.sig_files)}") - - active_sha1s = set() - self._precollect_inline_symbols() - self._build_shared_symbol_data() - self.struct_sha1_map = self._build_struct_sha1_map() - - need_translate = [] - for i, src_path in enumerate(py_files, 1): - rel = os.path.relpath(src_path, self.src_root) - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - sha1 = compute_sha1(content) - active_sha1s.add(sha1) - out_path = os.path.join(self.output_dir, f"{sha1}.ll") - - current_module_sha1_map = self._build_current_module_sha1_map(sha1) - - try: - tree = ast.parse(content) - for node in ast.walk(tree): - if isinstance(node, ast.Import): - for alias in node.names: - self.used_includes.add(alias.name.split('.')[0]) - elif isinstance(node, ast.ImportFrom): - if node.module: - self.used_includes.add(node.module.split('.')[0]) - except Exception: - pass - - if os.path.isfile(out_path): - deps_changed = self._check_deps_changed(sha1, current_module_sha1_map) - if not deps_changed: - print(f"[{i}/{len(py_files)}] 跳过(缓存): {rel} -> {sha1}.ll") - continue - else: - if self._recombine_ll(sha1, current_module_sha1_map): - print(f"[{i}/{len(py_files)}] 重组(依赖变化): {rel} -> {sha1}.ll") - continue - print(f"[{i}/{len(py_files)}] 重译(依赖变化): {rel} -> {sha1}.ll") - - else: - stub_cache = os.path.join(self.output_dir, f"{sha1}.stub.ll") - text_cache = os.path.join(self.output_dir, f"{sha1}.text.ll") - if os.path.isfile(stub_cache) and os.path.isfile(text_cache): - if self._recombine_ll(sha1, current_module_sha1_map): - print(f"[{i}/{len(py_files)}] 重组(缓存恢复): {rel} -> {sha1}.ll") - continue - - need_translate.append((i, src_path, out_path, sha1, current_module_sha1_map)) - - if need_translate: - print(f"\n[阶段二] 需要翻译 {len(need_translate)} 个文件") - import time - t_start = time.time() - - n_workers = min(os.cpu_count() or 4, len(need_translate), 8) - - if n_workers > 1 and len(need_translate) > 1: - from concurrent.futures import ProcessPoolExecutor, as_completed - import pickle - print(f" 并行翻译 (workers={n_workers})") - - shared_pickle_path = os.path.join(self.temp_dir, '_shared_sym.pkl') - try: - shared_data = { - 'symbol_table': self._shared_symbol_table, - 'source_module_sig_files': self._shared_source_module_sig_files, - 'all_dc': self._shared_all_dc, - 'export_extern_funcs': self._shared_export_extern_funcs, - 'inline_func_symbols': self.inline_func_symbols, - 'function_default_args': self.function_default_args, - 'generic_class_templates': self._shared_generic_class_templates, - } - with open(shared_pickle_path, 'wb') as f: - pickle.dump(shared_data, f, protocol=pickle.HIGHEST_PROTOCOL) - print(f" 共享符号表已序列化 ({os.path.getsize(shared_pickle_path)//1024}KB)") - except Exception as e: - print(f" [警告] 符号表序列化失败({e}),worker将自行构建") - shared_pickle_path = '' - - errors = [] - with ProcessPoolExecutor(max_workers=n_workers) as executor: - futures = {} - for i, src_path, out_path, sha1, msm in need_translate: - rel = os.path.relpath(src_path, self.src_root) - future = executor.submit( - _parallel_translate_worker, - src_path, out_path, - self.src_root, self.temp_dir, self.output_dir, - self.include_dirs, self.triple, self.datalayout, - self.sha1_map, self.sig_files, self.stub_files, - self.include_py_map, self.slice_level, - shared_pickle_path, self.struct_sha1_map - ) - futures[future] = (i, rel) - - done_count = 0 - for future in as_completed(futures): - i, rel = futures[future] - done_count += 1 - try: - status, _, err = future.result() - if status == 'ok': - print(f" [{done_count}/{len(need_translate)}] 完成: {rel}") - else: - print(f" [错误] {rel}: {err[:2000]}") - errors.append((rel, err)) - except Exception as e: - print(f" [错误] {rel}: {e}") - errors.append((rel, str(e))) - - if errors: - print(f"\n[编译终止] {len(errors)} 个文件翻译失败") - sys.exit(1) - else: - for idx, (i, src_path, out_path, sha1, msm) in enumerate(need_translate): - rel = os.path.relpath(src_path, self.src_root) - t0 = time.time() - try: - self._translate_file(src_path, out_path, prebuilt_module_sha1_map=msm) - t1 = time.time() - print(f" [{idx+1}/{len(need_translate)}] {rel} ({t1-t0:.1f}s)") - except Exception as e: - print(f" [错误] {rel}: {e}") - traceback.print_exc() - print(f"\n[编译终止] 翻译失败") - sys.exit(1) - t_end = time.time() - print(f" 翻译总耗时: {t_end-t_start:.1f}s") - - print(f"\n[阶段二完成] .ll 文件生成到: {self.output_dir}") - self._scan_include_libraries() - self._compile_include_py_files(active_sha1s) - self._compile_ll_files(active_sha1s) - self._compile_include_sources() - if self.linker_cmd: - self._link_obj_files(active_sha1s) - - def _build_current_module_sha1_map(self, self_sha1: str) -> dict: - """构建当前模块的依赖 SHA1 映射(与 _translate_file 中逻辑一致)""" - module_sha1_map = {} - for sha1_key, sig_path in self.sig_files.items(): - if sha1_key == self_sha1: - continue - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if rel_path.startswith('includes/'): - inc_mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - inc_mod_name = inc_mod_name[len('includes/'):] - inc_short_name = inc_mod_name.split('.')[-1] if '.' in inc_mod_name else inc_mod_name - actual_sha1 = sha1_key - for inc_dir in self.include_dirs: - if os.path.isdir(inc_dir): - py_path = os.path.join(inc_dir, rel_path[len('includes/'):].replace(os.sep, '/')) - py_path = os.path.splitext(py_path)[0] + '.py' - if os.path.isfile(py_path): - with open(py_path, 'r', encoding='utf-8') as f: - py_sha1 = compute_sha1(f.read()) - actual_sha1 = py_sha1 - break - module_sha1_map[inc_mod_name] = actual_sha1 - module_sha1_map[inc_short_name] = actual_sha1 - # Also add parent package name (e.g., 'hashlib' for 'hashlib.__init__') - if inc_short_name == '__init__' and '.' in inc_mod_name: - parent_pkg = inc_mod_name.rsplit('.', 1)[0] - module_sha1_map[parent_pkg] = actual_sha1 - continue - module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - module_sha1_map[module_name] = sha1_key - short_name = module_name.split('.')[-1] if '.' in module_name else module_name - module_sha1_map[short_name] = sha1_key - return module_sha1_map - - @staticmethod - def _split_ll(ll_content: str): - """将 .ll 内容拆分为 stub(声明)和 text(代码)两部分 - - stub: target, 注释, %type = type, declare, @xxx = external global - text: define ... { ... }, @xxx = global/constant (带初始化器) - """ - import re - stub_lines = [] - text_lines = [] - in_define = False - brace_depth = 0 - module_sha1 = None - defined_names = set() - - for line in ll_content.splitlines(True): - stripped = line.strip() - - if stripped.startswith('define '): - dm = re.match(r'define\s+[^@]*@"?([a-f0-9]+)\.', stripped) - if dm and module_sha1 is None: - module_sha1 = dm.group(1) - dm2 = re.match(r'define\s+[^@]*@"?([^"\s(]+)"?', stripped) - if dm2: - defined_names.add(dm2.group(1)) - - in_global_def = False - global_var_name = None - global_type_parts = [] - global_brace_depth = 0 - - for line in ll_content.splitlines(True): - stripped = line.strip() - - if in_global_def: - text_lines.append(line) - global_type_parts.append(stripped) - global_brace_depth += stripped.count('{') - stripped.count('}') - if global_brace_depth <= 0: - full_type = ' '.join(global_type_parts).strip() - depth = 0 - type_end = len(full_type) - for ci, cc in enumerate(full_type): - if cc in ('{', '['): - depth += 1 - elif cc in ('}', ']'): - depth -= 1 - elif depth == 0 and cc == ' ': - type_end = ci - break - var_type = full_type[:type_end].strip() - if var_type: - stub_lines.append(f'{global_var_name} = external global {var_type}\n') - in_global_def = False - global_var_name = None - global_type_parts = [] - global_brace_depth = 0 - continue - - if in_define: - text_lines.append(line) - brace_depth += stripped.count('{') - stripped.count('}') - if brace_depth <= 0: - in_define = False - continue - - if stripped.startswith('define '): - text_lines.append(line) - in_define = True - brace_depth = stripped.count('{') - stripped.count('}') - decl_line = re.sub(r'^define\s+', 'declare ', stripped) - decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) - decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) - paren_pos = decl_line.rfind(')') - if paren_pos >= 0: - decl_line = decl_line[:paren_pos + 1] - stub_lines.append(decl_line + '\n') - continue - - if stripped == '{' and text_lines and not in_define: - prev_stripped = text_lines[-1].strip() if text_lines else '' - if prev_stripped.startswith('define ') or prev_stripped.endswith('noredzone') or prev_stripped.endswith(')'): - text_lines.append(line) - brace_depth = 1 - in_define = True - if prev_stripped.startswith('define '): - decl_line = re.sub(r'^define\s+', 'declare ', prev_stripped) - decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) - decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) - paren_pos = decl_line.rfind(')') - if paren_pos >= 0: - decl_line = decl_line[:paren_pos + 1] - stub_lines.append(decl_line + '\n') - continue - - if stripped.startswith('@') and ' global ' in stripped and 'external global' not in stripped: - text_lines.append(line) - if ' internal ' not in stripped and ' private ' not in stripped: - name_match = re.match(r'(@\S+)', stripped) - if name_match: - var_name = name_match.group(1) - global_pos = stripped.find(' global ') - after_global = stripped[global_pos + 8:] - depth = 0 - type_end = len(after_global) - for ci, cc in enumerate(after_global): - if cc in ('{', '['): - depth += 1 - elif cc in ('}', ']'): - depth -= 1 - elif depth == 0 and cc == ' ': - type_end = ci - break - var_type = after_global[:type_end].strip() - brace_depth_gv = 0 - for cc in var_type: - if cc == '{': - brace_depth_gv += 1 - elif cc == '}': - brace_depth_gv -= 1 - if brace_depth_gv > 0: - in_global_def = True - global_var_name = var_name - global_type_parts = [var_type] - global_brace_depth = brace_depth_gv - elif var_type: - stub_lines.append(f'{var_name} = external global {var_type}\n') - continue - if stripped.startswith('@') and ' constant ' in stripped: - text_lines.append(line) - continue - - if stripped.startswith('declare'): - dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) - if dm: - fname = dm.group(1) - if fname in defined_names: - stub_lines.append(line) - continue - dot_pos = fname.find('.') - if dot_pos > 0: - fname_sha1 = fname[:dot_pos] - if module_sha1 and fname_sha1 != module_sha1 and len(fname_sha1) >= 16: - continue - if re.match(r'^[a-f0-9]{16}\.', fname): - continue - stub_lines.append(line) - continue - - stub_lines.append(line) - - return ''.join(stub_lines), ''.join(text_lines) - - def _save_deps(self, sha1: str, module_sha1_map: dict): - """保存依赖指纹到 .deps.json""" - deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") - deps = {} - for mod_name, dep_sha1 in module_sha1_map.items(): - deps[mod_name] = dep_sha1 - with open(deps_path, 'w', encoding='utf-8') as f: - json.dump(deps, f) - - def _load_deps(self, sha1: str) -> dict: - """加载依赖指纹""" - deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") - if os.path.isfile(deps_path): - try: - with open(deps_path, 'r', encoding='utf-8') as f: - return json.load(f) - except Exception: - pass - return None - - def _check_deps_changed(self, sha1: str, current_module_sha1_map: dict) -> bool: - """检查依赖指纹是否变化""" - saved_deps = self._load_deps(sha1) - if saved_deps is None: - return True - for mod_name, dep_sha1 in current_module_sha1_map.items(): - if saved_deps.get(mod_name) != dep_sha1: - return True - for mod_name, dep_sha1 in saved_deps.items(): - if current_module_sha1_map.get(mod_name) != dep_sha1: - return True - return False - - def _recombine_ll(self, sha1: str, current_module_sha1_map: dict) -> bool: - """依赖变化时重新组合 .ll:更新 .stub.ll 中的 SHA1 前缀,拼接 .stub.ll + .text.ll""" - saved_deps = self._load_deps(sha1) - if saved_deps is None: - return False - - stub_path = os.path.join(self.output_dir, f"{sha1}.stub.ll") - text_path = os.path.join(self.output_dir, f"{sha1}.text.ll") - ll_path = os.path.join(self.output_dir, f"{sha1}.ll") - - if not os.path.isfile(stub_path) or not os.path.isfile(text_path): - return False - - with open(stub_path, 'r', encoding='utf-8') as f: - stub_content = f.read() - with open(text_path, 'r', encoding='utf-8') as f: - text_content = f.read() - - sha1_replacements = {} - for mod_name, old_sha1 in saved_deps.items(): - new_sha1 = current_module_sha1_map.get(mod_name) - if new_sha1 and old_sha1 != new_sha1: - sha1_replacements[old_sha1] = new_sha1 - - if sha1_replacements: - for old_sha1, new_sha1 in sha1_replacements.items(): - stub_content = stub_content.replace(old_sha1, new_sha1) - text_content = text_content.replace(old_sha1, new_sha1) - - combined = stub_content - if not combined.endswith('\n'): - combined += '\n' - combined += text_content - - with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(combined) - with open(stub_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(stub_content) - with open(text_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(text_content) - - self._save_deps(sha1, current_module_sha1_map) - - obj_path = os.path.join(self.output_dir, f"{sha1}.obj") - if os.path.isfile(obj_path): - os.remove(obj_path) - - return True - - def _translate_file(self, src_path: str, out_path: str, prebuilt_module_sha1_map: dict = None): - """翻译单个源文件,嵌入相关 .stub.ll 声明""" - with open(src_path, 'r', encoding='utf-8') as f: - code = f.read() - - sha1 = compute_sha1(code) - - if prebuilt_module_sha1_map is not None: - module_sha1_map = prebuilt_module_sha1_map - else: - module_sha1_map = self._build_current_module_sha1_map(sha1) - - trans = TransPyC.TransPyC(code=code, triple=self.triple, datalayout=self.datalayout) - trans.translator.CurrentFile = src_path - trans.SliceLevel = self.slice_level - trans.translator.SliceLevel = self.slice_level - trans.translator.SliceCount = 0 - trans.translator.SliceInfos = [] - trans.translator.LlvmGen = None - trans.translator._module_sha1 = sha1 - trans.translator._module_sha1_map = module_sha1_map - trans.translator._struct_sha1_map = self.struct_sha1_map - trans.translator._global_function_default_args = self.function_default_args - trans.translator._temp_dir = self.temp_dir - - if hasattr(self, '_shared_symbol_table') and self._shared_symbol_table is not None: - trans.translator.SymbolTable = self._shared_symbol_table - # 确保共享符号表的 translator 指向当前 translator,以便 import 别名解析正确 - if hasattr(self._shared_symbol_table, 'translator'): - self._shared_symbol_table.translator = trans.translator - trans.translator._source_module_sig_files = self._shared_source_module_sig_files - trans.translator._all_define_constants = self._shared_all_dc - trans.translator._export_extern_funcs = self._shared_export_extern_funcs - if hasattr(self, '_shared_generic_class_templates') and self._shared_generic_class_templates: - if not hasattr(trans.translator.ClassHandler, '_generic_class_templates'): - trans.translator.ClassHandler._generic_class_templates = {} - trans.translator.ClassHandler._generic_class_templates.update(self._shared_generic_class_templates) - else: - export_extern_funcs = set() - for sha1_key, sig_path in self.sig_files.items(): - if sha1_key == sha1: - continue - try: - with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() - sig_tree = ast.parse(sig_content) - for node in ast.iter_child_nodes(sig_tree): - if isinstance(node, ast.FunctionDef): - if _check_annotation_for_export(node.returns): - export_extern_funcs.add(node.name) - except Exception: - pass - if export_extern_funcs: - trans.translator._export_extern_funcs = export_extern_funcs - - for includes_dir in self.include_dirs: - if os.path.isdir(includes_dir): - for pyi_file in os.listdir(includes_dir): - if pyi_file.endswith('.pyi'): - pyi_path = os.path.join(includes_dir, pyi_file) - module_name = os.path.splitext(pyi_file)[0] - trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) - for py_file in os.listdir(includes_dir): - if py_file.endswith('.py') and not py_file.startswith('_'): - module_name = os.path.splitext(py_file)[0] - sha1_key = self.include_py_map.get(module_name) - if sha1_key and sha1_key in self.sig_files: - sig_path = self.sig_files[sha1_key] - trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) - for sha1_key, sig_path in self.sig_files.items(): - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if rel_path.startswith('includes/'): - mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - mod_name = mod_name[len('includes/'):] - trans.translator.SymbolTable.LoadModuleSymbols(sig_path, mod_name, lineno=0) - if mod_name.endswith('.__init__'): - package_name = mod_name[:-len('.__init__')] - self._register_package_reexports(trans, sig_path, package_name) - - for sha1_key, sig_path in self.sig_files.items(): - if sha1_key == sha1: - continue - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if rel_path.startswith('includes/'): - continue - module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) - trans.translator._source_module_sig_files[module_name] = sig_path - short_name = module_name.split('.')[-1] if '.' in module_name else module_name - if short_name != module_name: - trans.translator._source_module_sig_files[short_name] = sig_path - - all_dc = {} - for sha1_key, stub_path in self.stub_files.items(): - if sha1_key == sha1: - continue - if os.path.exists(stub_path): - try: - with open(stub_path, 'r', encoding='utf-8') as f: - stub_content = f.read() - for line in stub_content.splitlines(): - line = line.strip() - if line.startswith('@') and '= global' in line and 'i32' in line and not line.startswith('@llvm'): - var_name = line.split('=')[0].strip().lstrip('@') - val_part = line.split('i32')[-1].strip().rstrip(']').lstrip('[').lstrip('i32') - try: - val = int(val_part) - all_dc[var_name] = val - except: - pass - except: - pass - for sha1_key, pyi_path in self.sig_files.items(): - if sha1_key == sha1: - continue - if os.path.exists(pyi_path): - try: - import ast as _ast - with open(pyi_path, 'r', encoding='utf-8') as f: - pyi_content = f.read() - tree = _ast.parse(pyi_content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): - ann_str = _ast.dump(node.annotation) - if 'CDefine' in ann_str and node.value: - val = None - if isinstance(node.value, _ast.Constant): - val = node.value.value - elif isinstance(node.value, _ast.Call) and isinstance(node.value.func, _ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], _ast.Constant): - val = node.value.args[0].value - if val is not None: - all_dc[f"{node.target.id}"] = val - except: - pass - if all_dc: - trans.translator._all_define_constants = all_dc - - for sym_name, sym_info in self.inline_func_symbols.items(): - if sym_name not in trans.translator.SymbolTable: - trans.translator.SymbolTable[sym_name] = sym_info - else: - existing = trans.translator.SymbolTable[sym_name] - if not getattr(existing, 'InlineBody', None) and getattr(sym_info, 'InlineBody', None): - existing.IsInline = sym_info.IsInline - existing.InlineBody = sym_info.InlineBody - existing.InlineParams = sym_info.InlineParams - - try: - result = trans.Convert( - OutputFilename=out_path, - SourceFilename=src_path, - target='llvm' - ) - except Exception as e: - error_stack = getattr(trans.translator, '_error_stack', []) - if error_stack: - self._last_error_stack = error_stack - chain_lines = [] - for entry in reversed(error_stack): - if len(entry) >= 3: - exc_msg, line_info = entry[1], entry[2] - chain_lines.append(" %s\n %s" % (line_info, exc_msg)) - if chain_lines: - enriched = str(e) + "\n" + "\n".join(chain_lines) - raise type(e)(enriched) from e - node_info = "" - if hasattr(trans.translator, 'LlvmGen') and trans.translator.LlvmGen: - node_info = trans.translator.LlvmGen._get_node_info() - if node_info: - enriched = "%s\n %s" % (str(e), node_info.strip()) - raise type(e)(enriched) from e - raise - - if result and isinstance(result, str): - for func_name, func_def in trans.translator.FunctionDefCache.items(): - if hasattr(func_def, 'args') and hasattr(func_def.args, 'defaults') and func_def.args.defaults: - mangled = trans.translator.LlvmGen._mangle_func_name(func_name) if trans.translator.LlvmGen else func_name - defaults = [] - for d in func_def.args.defaults: - if isinstance(d, ast.Constant): - defaults.append(d.value) - else: - defaults.append(None) - self.function_default_args[mangled] = defaults - self.function_default_args[func_name] = defaults - for sym_name, sym_info in trans.translator.SymbolTable.items(): - if isinstance(sym_info, CTypeInfo) and getattr(sym_info, 'IsInline', False) and getattr(sym_info, 'InlineBody', None): - self.inline_func_symbols[sym_name] = sym_info - # stub声明现在通过_dso.ll编译时拼接依赖模块stub.ll提供 - # stub_decls = self._collect_stub_decls_for_module(sha1) - # if stub_decls: - # result = self._inject_stub_decls(result, stub_decls) - - out_dir = os.path.dirname(out_path) - if out_dir: - os.makedirs(out_dir, exist_ok=True) - with open(out_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(result) - - stub_content, text_content = self._split_ll(result) - base = os.path.splitext(out_path)[0] - with open(base + '.stub.ll', 'w', encoding='utf-8', newline='\n') as f: - f.write(stub_content) - with open(base + '.text.ll', 'w', encoding='utf-8', newline='\n') as f: - f.write(text_content) - self._save_deps(sha1, module_sha1_map) - - print(f" -> {os.path.basename(out_path)}") - else: - stub_path = self.stub_files.get(sha1) - if stub_path and os.path.exists(stub_path): - out_dir = os.path.dirname(out_path) - if out_dir: - os.makedirs(out_dir, exist_ok=True) - with open(stub_path, 'r', encoding='utf-8') as f: - stub_content = f.read() - with open(out_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(stub_content) - print(f" -> {os.path.basename(out_path)} (仅声明)") - - def _register_package_reexports(self, trans, init_pyi_path, package_name): - """解析 __init__.pyi 中的 from .xxx import yyy 或 from __xxx import yyy,在包级别注册导出符号""" - try: - with open(init_pyi_path, 'r', encoding='utf-8') as f: - content = f.read() - tree = ast.parse(content) - for node in ast.walk(tree): - if isinstance(node, ast.ImportFrom) and node.module: - sub_module = node.module.lstrip('.') - for alias in node.names: - symbol_name = alias.name - exported_name = alias.asname if alias.asname else symbol_name - source_keys = [ - f"{package_name}.{sub_module}.{symbol_name}", - f"{package_name}.__{sub_module}.{symbol_name}" if not sub_module.startswith('__') else None, - symbol_name, - ] - target_key = f"{package_name}.{exported_name}" - if target_key not in trans.translator.SymbolTable: - for source_key in source_keys: - if source_key and source_key in trans.translator.SymbolTable: - trans.translator.SymbolTable[target_key] = trans.translator.SymbolTable[source_key] - break - if exported_name not in trans.translator.SymbolTable: - for source_key in source_keys: - if source_key and source_key in trans.translator.SymbolTable: - trans.translator.SymbolTable[exported_name] = trans.translator.SymbolTable[source_key] - break - except Exception as e: - print(f" [警告] 解析包重导出失败 {init_pyi_path}: {e}") - - def _collect_stub_decls(self, self_sha1: str) -> str: - """收集 includes 目录中模块的 .stub.ll 声明内容,去重""" - seen_symbols = set() - decl_lines = [] - for sha1_key, stub_path in self.stub_files.items(): - if sha1_key == self_sha1: - continue - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if not rel_path.startswith('includes/'): - continue - if os.path.exists(stub_path): - with open(stub_path, 'r', encoding='utf-8') as f: - content = f.read() - for line in content.splitlines(): - stripped = line.strip() - if not stripped: - continue - if stripped.startswith(';'): - continue - if stripped.startswith('target '): - continue - if stripped.startswith('source_filename'): - continue - if stripped.startswith('@') and '=' in stripped: - name = stripped.split('=', 1)[0].strip() - if name in seen_symbols: - continue - seen_symbols.add(name) - elif stripped.startswith('%') and '= type' in stripped: - name = stripped.split('=', 1)[0].strip() - if name in seen_symbols: - continue - seen_symbols.add(name) - elif stripped.startswith('declare'): - parts = stripped.split('@', 1) - if len(parts) > 1: - name = '@' + parts[1].split('(', 1)[0].strip() - if name in seen_symbols: - continue - seen_symbols.add(name) - decl_lines.append(line) - if decl_lines: - result = '\n'.join(decl_lines) - self._stub_decls_cache[self_sha1] = result - return result - self._stub_decls_cache[self_sha1] = '' - return '' - - def _collect_stub_decls_for_module(self, self_sha1: str) -> str: - """收集特定模块需要的 .stub.ll 声明(包括结构体类型定义、函数声明和 typedef)""" - if self_sha1 in self._stub_decls_cache: - return self._stub_decls_cache[self_sha1] - import re - seen_symbols = set() - seen_func_symbols = set() - decl_lines = [] - - non_struct_types = {'UINT', 'INT', 'BYTE', 'BYTEPTR', 'WORD', 'DWORD', 'QWORD', - 'INT8', 'INT16', 'INT32', 'INT64', 'UINT8', 'UINT16', 'UINT32', 'UINT64', - 'INTPTR', 'UINTPTR', 'SIZE_T', 'SSIZE_T', 'PTRDIFF_T', - 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', - 'atomic_int', 'atomic_uint', 'atomic_long', 'atomic_ulong', - 'atomic_int8', 'atomic_uint8', 'atomic_int16', 'atomic_uint16', - 'atomic_int32', 'atomic_uint32', 'atomic_int64', 'atomic_uint64', - 'atomic_ptr', 'atomic_flag', 'typedef', - 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array'} - - struct_names = set() - struct_source_sha1 = {} - - def _extract_struct_name(type_def_str): - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=\s*type', type_def_str) - if m: - raw = m.group(1) - if '.' in raw: - return raw.split('.', 1)[1], raw.split('.', 1)[0] - return raw, None - return None, None - - def _replace_struct_refs(type_str): - def replace_struct_name(name): - if name in struct_names: - name_sha1 = struct_source_sha1.get(name, '') - return f'%"{name_sha1}.{name}"' if name_sha1 else None - return None - def replace_struct_match(match): - name = match.group(1) - replaced = replace_struct_name(name) - return replaced if replaced else match.group(0) - def replace_sha1_struct_match(match): - name = match.group(2) - replaced = replace_struct_name(name) - return replaced if replaced else match.group(0) - result = re.sub(r'%struct\.(\w+)', replace_struct_match, type_str) - result = re.sub(r'%"?([a-f0-9]+)\.(\w+)"?', replace_sha1_struct_match, result) - return result - - for sha1_key, stub_path in self.stub_files.items(): - if os.path.exists(stub_path): - with open(stub_path, 'r', encoding='utf-8') as f: - content = f.read() - for line in content.splitlines(): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - clean_name, sha1_part = _extract_struct_name(stripped) - if clean_name and clean_name not in non_struct_types: - struct_names.add(clean_name) - if clean_name not in struct_source_sha1: - struct_source_sha1[clean_name] = sha1_part or sha1_key - - for sha1_key, stub_path in self.stub_files.items(): - if sha1_key == self_sha1: - continue - if os.path.exists(stub_path): - with open(stub_path, 'r', encoding='utf-8') as f: - content = f.read() - for line in content.splitlines(): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - clean_name, sha1_part = _extract_struct_name(stripped) - if not clean_name or clean_name in non_struct_types: - continue - if clean_name in seen_symbols: - continue - parts = stripped.split('= type', 1) - struct_type_body = parts[1].strip() if len(parts) > 1 else '' - if 'opaque' in struct_type_body: - seen_symbols.add(clean_name) - name_sha1 = struct_source_sha1.get(clean_name, sha1_key) - decl_lines.append(f'%"{name_sha1}.{clean_name}" = type opaque') - continue - if clean_name in struct_names: - struct_type_body = _replace_struct_refs(struct_type_body) - name_sha1 = struct_source_sha1.get(clean_name, sha1_key) - new_def = f'%"{name_sha1}.{clean_name}" = type {struct_type_body}' - seen_symbols.add(clean_name) - decl_lines.append(new_def) - if decl_lines: - return '\n'.join(decl_lines) - return '' - - def _inject_stub_decls(self, ll_content: str, stub_decls: str) -> str: - """将 stub 声明注入到 LLVM IR 模块头之后,替换 opaque 类型为具体定义""" - def normalize_type_name(name): - name = name.strip() - if name.startswith('%'): - return '%' + name[1:].strip().strip('"') - return name - - existing_symbols = {} # normalized_name -> (line_index, full_line) - for i, line in enumerate(ll_content.splitlines()): - stripped = line.strip() - if stripped.startswith('@') and '=' in stripped: - name = stripped.split('=', 1)[0].strip() - existing_symbols[name] = (i, line) - elif stripped.startswith('%') and '= type' in stripped: - name = normalize_type_name(stripped.split('=', 1)[0].strip()) - existing_symbols[name] = (i, line) - elif stripped.startswith('declare') or stripped.startswith('define'): - parts = stripped.split('@', 1) - if len(parts) > 1: - name = '@' + parts[1].split('(', 1)[0].strip() - existing_symbols[name] = (i, line) - - lines = ll_content.splitlines() - replacements = {} # line_index -> new_line - new_decls = [] # 新类型定义(不在现有输出中的) - - def normalize_type_name(name): - name = name.strip() - if name.startswith('%'): - return '%' + name[1:].strip().strip('"') - return name - - for line in stub_decls.splitlines(): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - name = normalize_type_name(stripped.split('=', 1)[0].strip()) - if name in existing_symbols: - idx, existing_line = existing_symbols[name] - existing_type_body = existing_line.strip().split('= type', 1)[1].strip() if '= type' in existing_line else '' - stub_type_body = stripped.split('= type', 1)[1].strip() if '= type' in stripped else '' - if 'opaque' in existing_line and 'opaque' not in stripped: - replacements[idx] = line - else: - new_decls.append(line) - - # 应用替换 - for idx, new_line in replacements.items(): - lines[idx] = new_line - - # 追加新类型定义到末尾(去重处理) - if new_decls: - # 过滤掉已经在 Translator 输出中存在的类型定义 - existing_types = set() - for line in lines: - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - type_name = normalize_type_name(stripped.split('=', 1)[0].strip()) - existing_types.add(type_name) - filtered_decls = [] - for line in new_decls: - stripped = line.strip() - if '= type' in stripped: - type_name = normalize_type_name(stripped.split('=', 1)[0].strip()) - if type_name not in existing_types: - filtered_decls.append(line) - existing_types.add(type_name) - if filtered_decls: - lines.append('') - lines.extend(filtered_decls) - - # 确保所有类型定义在全局变量之前,LLVM 要求在常量初始化器中使用类型之前必须先定义 - type_def_indices = [] - first_global_idx = None - for i, line in enumerate(lines): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - if first_global_idx is not None: - type_def_indices.append(i) - elif stripped.startswith('@') and ' global' in stripped: - if first_global_idx is None: - first_global_idx = i - - if type_def_indices and first_global_idx is not None: - type_defs = [lines[i] for i in reversed(type_def_indices)] - for i in reversed(type_def_indices): - del lines[i] - insert_pos = first_global_idx - if type_def_indices[0] < first_global_idx: - insert_pos = first_global_idx - len(type_def_indices) - for j, td in enumerate(type_defs): - lines.insert(insert_pos, td) - - result = '\n'.join(lines) - - return result - - def _compile_ll_files(self, active_sha1s: set): - """将 output_dir 中属于 active_sha1s 的 .ll 文件编译为 .obj(跳过已编译过的 include 文件)""" - stale_files = [] - for root, dirs, files in os.walk(self.output_dir): - for file in files: - fpath = os.path.join(root, file) - for ext in ('.ll', '.obj', '.stub.ll', '.text.ll', '.deps.json', '_dso.ll'): - if file.endswith(ext): - sha1 = file[:-(len(ext))] - if sha1 not in active_sha1s: - stale_files.append(fpath) - break - if stale_files: - for fpath in stale_files: - try: - os.remove(fpath) - except: - pass - print(f"[清理] 删除 {len(stale_files)} 个过时文件") - ll_files = [] - for root, dirs, files in os.walk(self.output_dir): - for file in files: - if file.endswith('.ll') and not file.endswith('.stub.ll') and not file.endswith('.text.ll'): - sha1 = file[:-3] - if sha1 in active_sha1s: - obj_path = os.path.join(root, file[:-3] + '.obj') - if not os.path.isfile(obj_path): - ll_files.append(os.path.join(root, file)) - - if not ll_files: - print("[编译] 无 .ll 文件需要重新编译") - else: - print(f"\n[编译] 找到 {len(ll_files)} 个 .ll 文件需要编译") - - has_inline = False - all_ll_files = [] - for root, dirs, files in os.walk(self.output_dir): - for file in files: - if file.endswith('.ll') and not file.endswith('.stub.ll') and not file.endswith('.text.ll'): - sha1 = file[:-3] - if sha1 in active_sha1s and sha1 not in self._include_sha1s: - all_ll_files.append(os.path.join(root, file)) - for ll_path in all_ll_files: - try: - with open(ll_path, 'r', encoding='utf-8') as f: - content = f.read() - if 'alwaysinline' in content: - has_inline = True - break - except: - pass - - if has_inline: - llvm_link = shutil.which('llvm-link') or shutil.which('llvm-link.exe') - opt_cmd = shutil.which('opt') or shutil.which('opt.exe') - if llvm_link and opt_cmd: - print(" [内联] 检测到 alwaysinline 函数,执行跨模块内联优化...") - for ll_path in all_ll_files: - try: - with open(ll_path, 'r', encoding='utf-8') as f: - content = f.read() - type_defs = [] - type_def_indices = set() - for i, line in enumerate(content.splitlines()): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - type_defs.append(line) - type_def_indices.add(i) - if type_def_indices: - lines = content.splitlines(True) - content_no_types = ''.join(line for i, line in enumerate(lines) if i not in type_def_indices) - header_end = 0 - for i, line in enumerate(content_no_types.splitlines()): - stripped = line.strip() - if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: - header_end = i + 1 - continue - break - lines2 = content_no_types.splitlines(True) - fixed = ''.join(lines2[:header_end]) + '\n'.join(type_defs) + '\n' + ''.join(lines2[header_end:]) - with open(ll_path, 'w', encoding='utf-8') as f: - f.write(fixed) - except: - pass - merged_ll = os.path.join(self.output_dir, '_merged.ll') - optimized_ll = os.path.join(self.output_dir, '_merged_opt.ll') - try: - link_cmd = [llvm_link] + all_ll_files + ['-o', merged_ll] - result = subprocess.run(link_cmd, capture_output=True, text=True) - if result.returncode != 0: - print(f" [警告] llvm-link 失败: {result.stderr.strip()},回退到单独编译") - has_inline = False - else: - opt_result_cmd = [opt_cmd, '-passes=always-inline', merged_ll, '-S', '-o', optimized_ll] - result = subprocess.run(opt_result_cmd, capture_output=True, text=True) - if result.returncode != 0: - print(f" [警告] opt 失败: {result.stderr.strip()},回退到单独编译") - has_inline = False - else: - print(" [内联] 跨模块内联优化完成") - with open(optimized_ll, 'r', encoding='utf-8') as f: - opt_content = f.read() - import re - opt_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', opt_content) - opt_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', opt_content) - opt_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', opt_content) - opt_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = linkonce_odr \2', opt_content) - with open(optimized_ll, 'w', encoding='utf-8') as f: - f.write(opt_content) - merged_obj = os.path.join(self.output_dir, '_merged.obj') - try: - cmd = [self.compile_cmd] + self.compile_flags + ['-o', merged_obj, optimized_ll] - result = subprocess.run(cmd, capture_output=True, text=True, - cwd=self.output_dir) - if result.returncode == 0: - print(f" [成功] 合并模块编译完成") - for ll_path in ll_files: - obj_path = ll_path[:-3] + '.obj' - sha1_obj = os.path.join(self.output_dir, os.path.basename(ll_path)[:-3] + '.obj') - if os.path.isfile(sha1_obj): - os.remove(sha1_obj) - return - else: - print(f" [警告] 合并模块编译失败: {result.stderr.strip()},回退到单独编译") - has_inline = False - except Exception as e: - print(f" [警告] 合并模块编译异常: {e},回退到单独编译") - has_inline = False - except FileNotFoundError: - print(f" [警告] 找不到 llvm-link 或 opt,回退到单独编译") - has_inline = False - else: - print(" [警告] 未找到 llvm-link/opt 工具,回退到单独编译(alwaysinline 可能不生效)") - - from concurrent.futures import ThreadPoolExecutor, as_completed - import re - - def _compile_one(ll_path): - rel = os.path.relpath(ll_path, self.output_dir) - obj_path = ll_path[:-3] + '.obj' - if os.path.isfile(obj_path): - return (rel, 'cached', '') - try: - with open(ll_path, 'r', encoding='utf-8') as f: - ll_content = f.read() - sha1 = os.path.basename(ll_path)[:-3] - deps = self._load_deps(sha1) - stub_prefix = '' - if deps: - existing_symbols = {} - opaque_line_indices = {} - existing_declares = set() - existing_declare_lines = {} - for i, line in enumerate(ll_content.splitlines()): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) - if m: - name = m.group(1) - if '= type opaque' in stripped: - existing_symbols[name] = 'opaque' - opaque_line_indices[name] = i - else: - existing_symbols[name] = 'full' - elif stripped.startswith('declare'): - dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) - if dm: - fname = dm.group(1) - existing_declares.add(fname) - existing_declare_lines[fname] = i - seen_stub_sha1 = set() - replaced_opaque_names = set() - replaced_declare_names = set() - all_stub_lines = [] - stub_type_map = {} - stub_declare_names = set() - stub_declare_lines = {} - existing_defines = set() - existing_global_defs = set() - stub_global_defs = set() - for line in ll_content.splitlines(): - stripped = line.strip() - if stripped.startswith('define'): - dm = re.match(r'define\s+[^@]*@"?([^"\s(]+)"?', stripped) - if dm: - existing_defines.add(dm.group(1)) - elif stripped.startswith('@') and (' global ' in stripped or ' constant ' in stripped): - gm = re.match(r'(@\S+)', stripped) - if gm: - existing_global_defs.add(gm.group(1)) - for dep_name, dep_sha1 in deps.items(): - if dep_sha1 in seen_stub_sha1: - continue - seen_stub_sha1.add(dep_sha1) - stub_path = os.path.join(self.output_dir, f"{dep_sha1}.stub.ll") - if not os.path.isfile(stub_path): - stub_path = os.path.join(self.temp_dir, f"{dep_sha1}.stub.ll") - if os.path.isfile(stub_path): - with open(stub_path, 'r', encoding='utf-8') as sf: - stub_content = sf.read() - for line in stub_content.splitlines(): - stripped = line.strip() - if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: - continue - if stripped.startswith('declare'): - dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) - if dm: - fname = dm.group(1) - if re.search(r'%("[^"]+"|[a-f0-9]+\.[A-Za-z_]\w*)\s+%', stripped): - continue - if fname in existing_defines: - continue - if fname in existing_declares or fname in stub_declare_names: - existing_decl_line = stub_declare_lines.get(fname) - if existing_decl_line is not None: - has_struct = '%' in stripped - existing_has_struct = '%' in existing_decl_line if existing_decl_line else False - if has_struct and not existing_has_struct: - for i, l in enumerate(all_stub_lines): - if l is not None and l.strip().startswith('declare'): - em = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', l.strip()) - if em and em.group(1) == fname: - all_stub_lines[i] = line - break - continue - elif fname in existing_declares: - has_struct = '%' in stripped - if has_struct: - replaced_declare_names.add(fname) - stub_declare_names.add(fname) - stub_declare_lines[fname] = line - all_stub_lines.append(line) - continue - continue - stub_declare_names.add(fname) - stub_declare_lines[fname] = line - all_stub_lines.append(line) - continue - if stripped.startswith('%') and '= type' in stripped: - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) - if m: - name = m.group(1) - is_opaque = '= type opaque' in stripped - if name in existing_symbols: - if existing_symbols[name] == 'opaque' and not is_opaque: - replaced_opaque_names.add(name) - existing_symbols[name] = 'full' - idx = len(all_stub_lines) - all_stub_lines.append(line) - stub_type_map[name] = (is_opaque, idx) - continue - if name in stub_type_map: - prev_opaque, prev_idx = stub_type_map[name] - if prev_opaque and not is_opaque: - all_stub_lines[prev_idx] = None - idx = len(all_stub_lines) - all_stub_lines.append(line) - stub_type_map[name] = (is_opaque, idx) - continue - idx = len(all_stub_lines) - all_stub_lines.append(line) - stub_type_map[name] = (is_opaque, idx) - else: - all_stub_lines.append(line) - elif stripped.startswith('@') and (' global ' in stripped or ' constant ' in stripped): - gm = re.match(r'(@\S+)', stripped) - if gm and (gm.group(1) in existing_global_defs or gm.group(1) in stub_global_defs): - continue - if gm: - stub_global_defs.add(gm.group(1)) - all_stub_lines.append(line) - else: - all_stub_lines.append(line) - filtered = [l for l in all_stub_lines if l is not None] - if filtered: - stub_prefix = '\n'.join(filtered) + '\n' - lines_to_remove = set() - if replaced_opaque_names: - for name in replaced_opaque_names: - if name in opaque_line_indices: - lines_to_remove.add(opaque_line_indices[name]) - if replaced_declare_names: - for fname in replaced_declare_names: - if fname in existing_declare_lines: - lines_to_remove.add(existing_declare_lines[fname]) - if lines_to_remove: - ll_lines = ll_content.splitlines(True) - ll_content = ''.join(line for i, line in enumerate(ll_lines) if i not in lines_to_remove) - type_defs_in_ll = [] - type_def_line_indices = set() - for i, line in enumerate(ll_content.splitlines()): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - type_defs_in_ll.append(line) - type_def_line_indices.add(i) - if type_def_line_indices: - ll_lines = ll_content.splitlines(True) - ll_content = ''.join(line for i, line in enumerate(ll_lines) if i not in type_def_line_indices) - if type_defs_in_ll: - stub_prefix += '\n'.join(type_defs_in_ll) + '\n' - if stub_prefix: - header_end = 0 - for i, line in enumerate(ll_content.splitlines()): - stripped = line.strip() - if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: - header_end = i + 1 - continue - break - ll_lines = ll_content.splitlines(True) - ll_content = ''.join(ll_lines[:header_end]) + stub_prefix + ''.join(ll_lines[header_end:]) - ll_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content) - ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', ll_content) - ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) - ll_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content) - final_type_defs = [] - final_type_def_indices = set() - for i, line in enumerate(ll_content.splitlines()): - stripped = line.strip() - if stripped.startswith('%') and '= type' in stripped: - final_type_defs.append(line) - final_type_def_indices.add(i) - if final_type_def_indices: - final_lines = ll_content.splitlines(True) - ll_content_no_types = ''.join(line for i, line in enumerate(final_lines) if i not in final_type_def_indices) - header_end = 0 - for i, line in enumerate(ll_content_no_types.splitlines()): - stripped = line.strip() - if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: - header_end = i + 1 - continue - break - final_lines2 = ll_content_no_types.splitlines(True) - ll_content = ''.join(final_lines2[:header_end]) + '\n'.join(final_type_defs) + '\n' + ''.join(final_lines2[header_end:]) - dso_ll_path = ll_path[:-3] + '_dso.ll' - with open(dso_ll_path, 'w', encoding='utf-8') as f: - f.write(ll_content) - cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, dso_ll_path] - result = subprocess.run(cmd, capture_output=True, text=True, - cwd=os.path.dirname(ll_path) or '.') - if result.returncode == 0: - return (rel, 'ok', '') - else: - return (rel, 'error', result.stderr.strip()) - except FileNotFoundError: - return (rel, 'error', f'找不到编译器: {self.compile_cmd}') - except Exception as e: - return (rel, 'error', str(e)) - - need_compile = [] - for ll_path in ll_files: - obj_path = ll_path[:-3] + '.obj' - if not os.path.isfile(obj_path): - need_compile.append(ll_path) - - if need_compile: - n_workers = min(os.cpu_count() or 4, len(need_compile), 8) - print(f" 并行编译 {len(need_compile)} 个文件 (workers={n_workers})") - errors = [] - with ThreadPoolExecutor(max_workers=n_workers) as executor: - futures = {executor.submit(_compile_one, ll_path): ll_path for ll_path in need_compile} - for future in as_completed(futures): - rel, status, err = future.result() - if status == 'ok': - print(f" [成功] {rel}") - elif status == 'error': - print(f" [错误] {rel}: {err}") - errors.append((rel, err)) - elif status == 'cached': - pass - if errors: - print(f"\n[编译终止] {len(errors)} 个文件编译失败") - sys.exit(1) - - def _scan_include_libraries(self): - """扫描 includes 目录,检测被使用的模块对应的库文件和源文件""" - if not self.used_includes: - return - - for includes_dir in self.include_dirs: - if not os.path.isdir(includes_dir): - continue - - for module_name in self.used_includes: - module_dir = os.path.join(includes_dir, module_name) - if os.path.isdir(module_dir): - self._scan_dir_for_libs(module_dir, module_name) - for root, dirs, files in os.walk(module_dir): - dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] - for fname in files: - if fname.endswith('.py'): - py_path = os.path.join(root, fname) - if py_path not in self.extra_py_files: - self.extra_py_files.append(py_path) - print(f" [includes] 发现 Python 包文件: {os.path.relpath(py_path, includes_dir)}") - - for ext in self.INCLUDE_LIB_EXTENSIONS: - lib_path = os.path.join(includes_dir, module_name + ext) - if os.path.isfile(lib_path): - self.extra_link_files.append(lib_path) - print(f" [includes] 发现库文件: {os.path.relpath(lib_path, includes_dir)}") - - for ext in self.INCLUDE_SRC_EXTENSIONS: - src_path = os.path.join(includes_dir, module_name + ext) - if os.path.isfile(src_path): - self.extra_compile_files.append(src_path) - print(f" [includes] 发现源文件: {os.path.relpath(src_path, includes_dir)}") - - py_path = os.path.join(includes_dir, module_name + '.py') - if os.path.isfile(py_path): - self.extra_py_files.append(py_path) - print(f" [includes] 发现 Python 源文件: {os.path.relpath(py_path, includes_dir)}") - - discovered = set() - for ef in list(self.extra_py_files): - self._discover_transitive_deps(ef, includes_dir, discovered) - - if self.extra_link_files: - print(f"\n[includes] 需要链接的库文件: {len(self.extra_link_files)} 个") - if self.extra_compile_files: - print(f"[includes] 需要编译的源文件: {len(self.extra_compile_files)} 个") - - def _scan_dir_for_libs(self, directory: str, module_name: str): - """递归扫描目录中的库文件和源文件""" - for root, dirs, files in os.walk(directory): - for fname in files: - fpath = os.path.join(root, fname) - _, ext = os.path.splitext(fname) - ext = ext.lower() - if ext in self.INCLUDE_LIB_EXTENSIONS: - self.extra_link_files.append(fpath) - print(f" [includes] 发现库文件: {os.path.relpath(fpath, directory)}") - elif ext in self.INCLUDE_SRC_EXTENSIONS: - self.extra_compile_files.append(fpath) - print(f" [includes] 发现源文件: {os.path.relpath(fpath, directory)}") - - def _discover_transitive_deps(self, py_path: str, includes_dir: str, discovered: set): - """递归发现 Python 文件的间接依赖""" - if py_path in discovered: - return - discovered.add(py_path) - try: - with open(py_path, 'r', encoding='utf-8') as f: - content = f.read() - import ast as _ast - tree = _ast.parse(content) - for node in _ast.walk(tree): - if isinstance(node, _ast.Import): - for alias in node.names: - mod = alias.name.split('.')[0] - self._try_add_include_dep(mod, includes_dir, discovered) - elif isinstance(node, _ast.ImportFrom): - if node.module and node.level == 0: - mod = node.module.split('.')[0] - self._try_add_include_dep(mod, includes_dir, discovered) - except Exception: - pass - - def _try_add_include_dep(self, module_name: str, includes_dir: str, discovered: set): - """尝试将模块添加为 include 依赖""" - py_path = os.path.join(includes_dir, module_name + '.py') - if os.path.isfile(py_path) and py_path not in self.extra_py_files: - self.extra_py_files.append(py_path) - print(f" [includes] 发现间接依赖: {os.path.relpath(py_path, includes_dir)}") - self._discover_transitive_deps(py_path, includes_dir, discovered) - - def _is_decl_only_file(self, src_path: str) -> bool: - try: - with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - import ast as _ast - tree = _ast.parse(content) - for node in _ast.walk(tree): - if isinstance(node, _ast.ClassDef): - return False - if isinstance(node, _ast.FunctionDef): - body = node.body - if len(body) == 1: - stmt = body[0] - if isinstance(stmt, _ast.Expr) and isinstance(stmt.value, _ast.Constant) and stmt.value.value is ...: - continue - if isinstance(stmt, _ast.Pass): - continue - return False - return True - except Exception: - return False - - def _sort_include_files_by_deps(self, file_list: list) -> list: - """按依赖关系对 include 文件进行拓扑排序,确保被依赖的文件先编译""" - import ast as _ast - - # 构建文件名到路径的映射 - name_to_path = {} - for fpath in file_list: - basename = os.path.splitext(os.path.basename(fpath))[0] - name_to_path[basename] = fpath - - # 也支持包内模块: vpsdk/window -> path - for fpath in file_list: - # 尝试从 includes 目录推断模块全名 - for includes_dir in self.include_dirs: - try: - rel = os.path.relpath(fpath, includes_dir) - mod_name = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') - name_to_path[mod_name] = fpath - except ValueError: - pass - - # 分析每个文件的 import 依赖 - deps = {} # path -> set of paths it depends on - for fpath in file_list: - deps[fpath] = set() - try: - with open(fpath, 'r', encoding='utf-8') as f: - content = f.read() - tree = _ast.parse(content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.Import): - for alias in node.names: - mod = alias.name.split('.')[0] - if mod in name_to_path and name_to_path[mod] != fpath: - deps[fpath].add(name_to_path[mod]) - elif isinstance(node, _ast.ImportFrom): - if node.module and node.level == 0: - mod = node.module.split('.')[0] - if mod in name_to_path and name_to_path[mod] != fpath: - deps[fpath].add(name_to_path[mod]) - except Exception: - pass - - # 拓扑排序 (Kahn's algorithm) - in_degree = {fpath: len(deps[fpath]) for fpath in file_list} - # 反向邻接表:如果 A 依赖 B,则 B -> A - reverse_adj = {fpath: [] for fpath in file_list} - for fpath in file_list: - for dep in deps[fpath]: - if dep in reverse_adj: - reverse_adj[dep].append(fpath) - - result = [] - queue = [fpath for fpath in file_list if in_degree[fpath] == 0] - # 对队列排序以保持确定性 - queue.sort(key=lambda x: x) - - while queue: - current = queue.pop(0) - result.append(current) - for neighbor in reverse_adj[current]: - in_degree[neighbor] -= 1 - if in_degree[neighbor] == 0: - queue.append(neighbor) - queue.sort(key=lambda x: x) - - # 如果有循环依赖,把剩余文件也加入 - for fpath in file_list: - if fpath not in result: - result.append(fpath) - - return result - - def _compile_include_py_files(self, active_sha1s: set): - """通过 TransPyC 翻译器编译 includes 目录中发现的 .py 文件""" - if not self.extra_py_files: - return - - # 按依赖关系排序 include 文件,确保被依赖的文件先编译 - sorted_files = self._sort_include_files_by_deps(self.extra_py_files) - - print(f"\n[includes 编译] 找到 {len(sorted_files)} 个 Python 源文件") - - # 构建 include 文件的模块 SHA1 映射 - # 必须在编译前预构建完整的映射,否则后续文件引用前面文件时会用错误的 SHA1 - include_module_sha1_map = self._build_current_module_sha1_map(None) - # 预先为所有 include 文件计算 SHA1 并添加到映射中 - for src_path in sorted_files: - module_name = os.path.splitext(os.path.basename(src_path))[0] - with open(src_path, 'r', encoding='utf-8') as f: - py_content = f.read() - sha1 = compute_sha1(py_content) - self.include_py_map[module_name] = sha1 - active_sha1s.add(sha1) - self._include_sha1s.add(sha1) - - # 将 include 文件的模块名映射到其 SHA1 - for includes_dir in self.include_dirs: - try: - rel = os.path.relpath(src_path, includes_dir) - mod_full = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') - include_module_sha1_map[mod_full] = sha1 - include_module_sha1_map[module_name] = sha1 - except ValueError: - pass - include_module_sha1_map[module_name] = sha1 - ll_path = os.path.join(self.output_dir, f"{sha1}.ll") - obj_path = os.path.join(self.output_dir, f"{sha1}.obj") - - if self._is_decl_only_file(src_path): - print(f" 跳过(声明文件): {module_name}.py") - self._collect_inline_symbols(src_path) - continue - - if os.path.isfile(obj_path): - print(f" 跳过(缓存): {module_name}.py -> {sha1}.obj") - self._collect_inline_symbols(src_path) - self.extra_link_files.append(obj_path) - continue - - print(f" 翻译: {os.path.basename(src_path)} -> {sha1}.ll") - - try: - self._translate_file(src_path, ll_path, prebuilt_module_sha1_map=include_module_sha1_map) - if os.path.isfile(ll_path): - print(f" 编译: {sha1}.ll -> {sha1}.obj") - with open(ll_path, 'r', encoding='utf-8') as f: - ll_content = f.read() - import re - ll_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content) - ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)', r'\1 dso_local ', ll_content) - ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) - ll_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content) - stub_decls = [] - for other_sha1, other_stub in self.stub_files.items(): - if other_sha1 == sha1: - continue - if os.path.exists(other_stub): - try: - with open(other_stub, 'r', encoding='utf-8') as sf: - for sline in sf: - sl = sline.strip() - if sl.startswith('%') and '= type' in sl and 'opaque' not in sl: - struct_name_match = re.match(r'%"?([\w.]+)"?\s*=', sl) - if struct_name_match: - stub_decls.append(sl) - except: - pass - if stub_decls: - for sdecl in stub_decls: - sname_match = re.match(r'%"?([\w.]+)"?\s*=\s*type', sdecl) - if sname_match: - sname = sname_match.group(1) - short = sname.split('.')[-1] if '.' in sname else sname - ll_content = re.sub( - r'%"?' + re.escape(sname) + r'"?\s*=\s*type\s*opaque', - sdecl, ll_content) - if short != sname: - ll_content = re.sub( - r'%"?' + re.escape(short) + r'"?\s*=\s*type\s*opaque', - sdecl, ll_content) - dso_ll_path = ll_path[:-3] + '_dso.ll' - with open(dso_ll_path, 'w', encoding='utf-8') as f: - f.write(ll_content) - cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, dso_ll_path] - result = subprocess.run( - cmd, - capture_output=True, - text=True, - cwd=self.output_dir - ) - if result.returncode == 0: - print(f" [成功]") - self.extra_link_files.append(obj_path) - - # 编译成功后,生成 .pyi 签名文件和 .stub.ll 文件 - # 并注册到符号表和签名映射中,以便后续 include 文件可以引用 - self._register_compiled_include(src_path, sha1, ll_content, include_module_sha1_map) - else: - print(f" [警告] 编译失败: {result.stderr.strip()}") - for ext in ['.ll', '_dso.ll']: - p = ll_path[:-3] + ext - if os.path.isfile(p): - os.remove(p) - else: - print(f" [错误] 翻译未生成 .ll 文件") - except Exception as e: - import traceback - for ext in ['.ll', '_dso.ll']: - p = ll_path[:-3] + ext - if os.path.isfile(p): - os.remove(p) - print(f" [错误] 翻译异常: {e}") - traceback.print_exc() - print(f"\n[编译终止] includes 文件翻译失败") - sys.exit(1) - - def _register_compiled_include(self, src_path, sha1, ll_content, include_module_sha1_map): - """编译 include 文件成功后,生成签名和 stub 文件并注册到符号表中""" - module_name = os.path.splitext(os.path.basename(src_path))[0] - - # 确定完整模块名(如 vpsdk.window) - mod_full = module_name - for includes_dir in self.include_dirs: - try: - rel = os.path.relpath(src_path, includes_dir) - mod_full = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') - break - except ValueError: - pass - - # 1. 生成 .pyi 签名文件(如果还没有的话) - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") - if not os.path.isfile(sig_path): - try: - with open(src_path, 'r', encoding='utf-8') as f: - py_content = f.read() - sig_content = PythonToStubConverter.convert(py_content, mod_full) - os.makedirs(self.temp_dir, exist_ok=True) - with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(sig_content) - except Exception as e: - pass # 签名生成失败不阻塞编译 - - # 注册到 sig_files 和 _source_module_sig_files - if os.path.isfile(sig_path): - self.sig_files[sha1] = sig_path - self.sha1_map[sha1] = f"includes/{mod_full.replace('.', os.sep)}.py" - if hasattr(self, '_shared_source_module_sig_files') and self._shared_source_module_sig_files is not None: - self._shared_source_module_sig_files[mod_full] = sig_path - self._shared_source_module_sig_files[module_name] = sig_path - - # 将签名信息加载到共享符号表中 - if hasattr(self, '_shared_symbol_table') and self._shared_symbol_table is not None: - try: - self._shared_symbol_table.LoadModuleSymbols(sig_path, mod_full, lineno=0) - except Exception: - pass - - # 2. 生成 .stub.ll 文件 - stub_path = os.path.join(self.output_dir, f"{sha1}.stub.ll") - if not os.path.isfile(stub_path) and ll_content: - try: - stub_content, _ = self._split_ll(ll_content) - with open(stub_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(stub_content) - except Exception: - pass - - # 注册到 stub_files - if os.path.isfile(stub_path): - self.stub_files[sha1] = stub_path - elif os.path.isfile(sig_path): - # 如果 stub 文件不存在,也尝试从 temp 目录查找 - temp_stub = os.path.join(self.temp_dir, f"{sha1}.stub.ll") - if os.path.isfile(temp_stub): - self.stub_files[sha1] = temp_stub - - def _precollect_inline_symbols(self): - """在主翻译循环之前,扫描includes目录中used_includes相关的模块收集内联函数AST""" - if not self.used_includes: - return - for includes_dir in self.include_dirs: - if not os.path.isdir(includes_dir): - continue - for module_name in self.used_includes: - module_dir = os.path.join(includes_dir, module_name) - if os.path.isdir(module_dir): - for root, dirs, files in os.walk(module_dir): - dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] - for fname in files: - if fname.endswith('.py'): - src_path = os.path.join(root, fname) - self._collect_inline_symbols(src_path) - py_path = os.path.join(includes_dir, module_name + '.py') - if os.path.isfile(py_path): - self._collect_inline_symbols(py_path) - for ef in self.extra_py_files: - self._collect_inline_symbols(ef) - - def _collect_inline_symbols(self, src_path: str): - """解析源文件,收集内联函数的AST信息到inline_func_symbols""" - try: - with open(src_path, 'r', encoding='utf-8') as f: - code = f.read() - tree = ast.parse(code) - module_name = os.path.splitext(os.path.basename(src_path))[0] - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.FunctionDef) and node.returns: - is_inline = False - if isinstance(node.returns, ast.BinOp) and isinstance(node.returns.op, ast.BitOr): - for part in [node.returns.left, node.returns.right]: - if isinstance(part, ast.Attribute) and part.attr == 'CInline': - is_inline = True - break - if isinstance(part, ast.Name) and part.id == 'CInline': - is_inline = True - break - elif isinstance(node.returns, ast.Attribute) and node.returns.attr == 'CInline': - is_inline = True - elif isinstance(node.returns, ast.Name) and node.returns.id == 'CInline': - is_inline = True - if is_inline: - func_name = node.name - sym_key = f"{module_name}.{func_name}" - info = CTypeInfo() - info.Name = func_name - info.IsFunction = True - info.IsInline = True - info.InlineBody = node.body - info.InlineParams = [arg.arg for arg in node.args.args] - info.Storage = t.CInline() - self.inline_func_symbols[func_name] = info - self.inline_func_symbols[sym_key] = info - except Exception: - pass - - def _build_shared_symbol_data(self): - """一次性构建所有文件共享的符号表数据,避免每个文件重复加载""" - import copy - import time - t0 = time.time() - - print("[缓存] 构建共享符号表数据...") - - base_trans = TransPyC.TransPyC(code="pass", triple=self.triple, datalayout=self.datalayout) - base_trans.translator.LlvmGen = None - base_trans.translator._module_sha1_map = {} - base_trans.translator._global_function_default_args = self.function_default_args - - for includes_dir in self.include_dirs: - if os.path.isdir(includes_dir): - for pyi_file in os.listdir(includes_dir): - if pyi_file.endswith('.pyi'): - pyi_path = os.path.join(includes_dir, pyi_file) - module_name = os.path.splitext(pyi_file)[0] - base_trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) - for py_file in os.listdir(includes_dir): - if py_file.endswith('.py') and not py_file.startswith('_'): - module_name = os.path.splitext(py_file)[0] - sha1_key = self.include_py_map.get(module_name) - if sha1_key and sha1_key in self.sig_files: - sig_path = self.sig_files[sha1_key] - base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) - for sha1_key, sig_path in self.sig_files.items(): - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if rel_path.startswith('includes/'): - mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - mod_name = mod_name[len('includes/'):] - base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, mod_name, lineno=0) - if mod_name.endswith('.__init__'): - package_name = mod_name[:-len('.__init__')] - self._register_package_reexports(base_trans, sig_path, package_name) - - for sha1_key, sig_path in self.sig_files.items(): - rel_path = self.sha1_map.get(sha1_key, sha1_key) - if rel_path.startswith('includes/'): - continue - module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) - base_trans.translator._source_module_sig_files[module_name] = sig_path - short_name = module_name.split('.')[-1] if '.' in module_name else module_name - if short_name != module_name: - base_trans.translator._source_module_sig_files[short_name] = sig_path - - all_dc = {} - for sha1_key, stub_path in self.stub_files.items(): - if os.path.exists(stub_path): - try: - with open(stub_path, 'r', encoding='utf-8') as f: - stub_content = f.read() - for line in stub_content.splitlines(): - line = line.strip() - if line.startswith('@') and '= global' in line and 'i32' in line and not line.startswith('@llvm'): - var_name = line.split('=')[0].strip().lstrip('@') - val_part = line.split('i32')[-1].strip().rstrip(']').lstrip('[').lstrip('i32') - try: - val = int(val_part) - all_dc[var_name] = val - except: - pass - except: - pass - for sha1_key, pyi_path in self.sig_files.items(): - if os.path.exists(pyi_path): - try: - with open(pyi_path, 'r', encoding='utf-8') as f: - pyi_content = f.read() - tree = ast.parse(pyi_content) - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - ann_str = ast.dump(node.annotation) - if 'CDefine' in ann_str and node.value: - val = None - if isinstance(node.value, ast.Constant): - val = node.value.value - elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], ast.Constant): - val = node.value.args[0].value - if val is not None: - all_dc[f"{node.target.id}"] = val - except: - pass - - export_extern_funcs = set() - for sha1_key, sig_path in self.sig_files.items(): - try: - with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() - sig_tree = ast.parse(sig_content) - for node in ast.iter_child_nodes(sig_tree): - if isinstance(node, ast.FunctionDef): - if _check_annotation_for_export(node.returns): - export_extern_funcs.add(node.name) - except Exception: - pass - - for sym_name, sym_info in self.inline_func_symbols.items(): - if sym_name not in base_trans.translator.SymbolTable: - base_trans.translator.SymbolTable[sym_name] = sym_info - else: - existing = base_trans.translator.SymbolTable[sym_name] - if not getattr(existing, 'InlineBody', None) and getattr(sym_info, 'InlineBody', None): - existing.IsInline = sym_info.IsInline - existing.InlineBody = sym_info.InlineBody - existing.InlineParams = sym_info.InlineParams - - self._shared_symbol_table = base_trans.translator.SymbolTable - self._shared_source_module_sig_files = dict(base_trans.translator._source_module_sig_files) - self._shared_all_dc = all_dc - self._shared_export_extern_funcs = export_extern_funcs - - generic_class_templates = {} - for includes_dir in self.include_dirs: - if os.path.isdir(includes_dir): - abs_includes = os.path.join(self.src_root, includes_dir) if not os.path.isabs(includes_dir) else includes_dir - if not os.path.isdir(abs_includes): - abs_includes = includes_dir - for py_file in os.listdir(abs_includes): - if py_file.endswith('.py') and not py_file.startswith('_'): - py_path = os.path.join(abs_includes, py_file) - try: - with open(py_path, 'r', encoding='utf-8') as f: - py_code = f.read() - py_tree = ast.parse(py_code) - for node in py_tree.body: - if isinstance(node, ast.ClassDef) and hasattr(node, 'type_params') and node.type_params: - type_params = [tp.name for tp in node.type_params] - generic_class_templates[node.name] = { - 'node': node, - 'type_params': type_params, - } - except Exception: - pass - self._shared_generic_class_templates = generic_class_templates - - t1 = time.time() - print(f"[缓存] 共享符号表构建完成 ({t1-t0:.2f}s, {len(self._shared_symbol_table)} 符号, {len(generic_class_templates)} 泛型模板)") - - def _compile_include_sources(self): - """扫描项目目录中的汇编存根,编译 includes 目录中发现的 C/C++ 源文件""" - extra_sources = list(self.extra_compile_files) - scan_dirs = [] - if self.src_root and os.path.isdir(self.src_root): - scan_dirs.append(self.src_root) - project_dir = os.path.dirname(self.output_dir) - if project_dir and os.path.isdir(project_dir) and project_dir not in scan_dirs: - scan_dirs.append(project_dir) - for scan_dir in scan_dirs: - for root, dirs, files in os.walk(scan_dir): - dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] - for fname in files: - if fname.endswith(('.S', '.s', '.c', '.cpp')): - if fname.startswith('test_'): - continue - fpath = os.path.join(root, fname) - if fpath not in extra_sources: - extra_sources.append(fpath) - if not extra_sources: - return - - cc_map = { - '.c': 'gcc', - '.cpp': 'g++', '.cc': 'g++', '.cxx': 'g++', - '.m': 'clang', '.mm': 'clang++', - '.s': 'gcc', '.S': 'gcc', - } - - print(f"\n[includes 编译] 找到 {len(extra_sources)} 个源文件") - - for src_path in extra_sources: - _, ext = os.path.splitext(src_path) - ext = ext.lower() - obj_path = os.path.join(self.output_dir, os.path.splitext(os.path.basename(src_path))[0] + '.obj') - if ext in ('.s', '.S') and any('oformat' in f for f in self.linker_flags): - cc = 'clang' - compile_src = src_path - extra_flags = ['-c', '-target', 'x86_64-none-elf', '-o', obj_path, compile_src] - else: - cc = cc_map.get(ext, 'gcc') - extra_flags = ['-c', '-o', obj_path, src_path] - - print(f" 编译: {os.path.basename(src_path)} -> {os.path.basename(obj_path)}") - - try: - cmd = [cc] + extra_flags - result = subprocess.run(cmd, capture_output=True, text=True) - if result.returncode == 0: - print(f" [成功]") - self.extra_link_files.append(obj_path) - else: - print(f" [错误] 编译失败: {result.stderr.strip()}") - print(f"\n[编译终止] C/C++ 源文件编译失败,立即终止编译。") - sys.exit(1) - except FileNotFoundError: - print(f" [错误] 找不到编译器: {cc}") - print(f"\n[编译终止] 找不到编译器,立即终止编译。") - sys.exit(1) - except Exception as e: - print(f" [错误] {e}") - print(f"\n[编译终止] 编译异常,立即终止编译。") - sys.exit(1) - - def _strip_debug_sections(self, exe_path: str): - """剥离 .exe 中的调试段(跳过裸机二进制)""" - if not os.path.exists(exe_path): - return - ext = os.path.splitext(exe_path)[1].lower() - if ext not in ('.exe', '.dll', '.obj', '.o', '.elf'): - print(f" [剥离] 跳过({ext} 格式无需剥离)") - return - import shutil - for tool in ['llvm-strip', 'strip']: - strip_cmd = shutil.which(tool) - if strip_cmd: - try: - result = subprocess.run( - [strip_cmd, '--strip-debug', exe_path], - capture_output=True, text=True - ) - if result.returncode == 0: - print(f" [剥离] 调试段已移除 ({tool})") - else: - print(f" [剥离] 警告: {result.stderr.strip()}") - except Exception: - pass - break - - def _link_obj_files(self, active_sha1s: set): - """将 active_sha1s 对应的 .obj 文件和 includes 库文件链接为可执行文件""" - obj_files = [] - merged_obj = os.path.join(self.output_dir, '_merged.obj') - if os.path.isfile(merged_obj): - obj_files.append(merged_obj) - else: - for root, dirs, files in os.walk(self.output_dir): - for file in files: - if file.endswith('.obj'): - sha1 = file[:-4] - if sha1 in active_sha1s and sha1 not in self._include_sha1s: - obj_files.append(os.path.join(root, file)) - - if not obj_files and not self.extra_link_files: - print("[链接] 无文件可链接") - return - - print(f"\n[链接] 找到 {len(obj_files)} 个 .obj 文件") - - all_link_files = obj_files + self.extra_link_files - seen = set() - all_link_files = [f for f in all_link_files if not (f in seen or seen.add(f))] - if self.extra_link_files: - print(f"[链接] 额外库文件: {len(self.extra_link_files)} 个") - for lib in self.extra_link_files: - print(f" - {os.path.basename(lib)}") - - if not self.linker_cmd: - print("[链接] 未配置链接器") - return - - exe_path = os.path.join(self.output_dir, self.linker_output) if self.linker_output else os.path.join(self.output_dir, 'a.exe') - is_binary = self.linker_output and self.linker_output.endswith('.bin') - - # 检查是否直接输出二进制(使用 --oformat binary / -oformat binary 标志) - is_direct_binary = is_binary and any('oformat' in f for f in self.linker_flags) - - if is_binary and not is_direct_binary: - link_output = exe_path[:-4] + '_pe.exe' - else: - link_output = exe_path - - # 自动复制或生成 linker.ld 到输出目录 - linker_ld_src = os.path.join(os.path.dirname(self.output_dir), 'linker.ld') - linker_ld_dst = os.path.join(self.output_dir, 'linker.ld') - if os.path.isfile(linker_ld_src) and not os.path.isfile(linker_ld_dst): - import shutil - shutil.copy2(linker_ld_src, linker_ld_dst) - print(f" [链接] 使用链接脚本: linker.ld") - elif not os.path.isfile(linker_ld_dst) and any('-T' in f or '-T' in f.replace(',', ' ') for f in self.linker_flags): - default_ld = """ENTRY(_start) - -SECTIONS { - . = 0x100000; - - .text : { - *(.text.startup) - *(.text) - *(.text.*) - } - - .rodata : { - *(.rodata) - *(.rodata.*) - } - - .data : { - *(.data) - *(.data.*) - } - - .bss : { - *(.bss) - *(.bss.*) - } - - /DISCARD/ : { - *(.comment) - *(.note) - *(.eh_frame) - *(.eh_frame_hdr) - *(.reloc) - *(.rela) - *(.debug*) - } -} -""" - with open(linker_ld_dst, 'w', encoding='utf-8', newline='\n') as f: - f.write(default_ld) - print(f" [链接] 自动创建默认链接脚本: linker.ld") - - try: - cmd = [self.linker_cmd] + self.linker_flags + ['-o', link_output] + all_link_files - print(f" 执行: {' '.join(cmd)}") - result = subprocess.run( - cmd, - capture_output=True, - text=True, - cwd=self.output_dir or '.' - ) - if result.returncode == 0: - if is_binary and not is_direct_binary: - import shutil - objcopy = shutil.which('llvm-objcopy') or shutil.which('objcopy') - if objcopy: - conv = subprocess.run( - [objcopy, '-O', 'binary', link_output, exe_path], - capture_output=True, text=True - ) - if conv.returncode == 0: - os.remove(link_output) - print(f" [成功] 生成裸机二进制: {exe_path}") - file_size = os.path.getsize(exe_path) - print(f" [大小] {file_size} 字节") - else: - print(f" [错误] 二进制转换失败: {conv.stderr.strip()}") - sys.exit(1) - else: - print(" [错误] 找不到 llvm-objcopy,无法生成裸机二进制") - sys.exit(1) - else: - print(f" [成功] 生成: {exe_path}") - file_size = os.path.getsize(exe_path) - print(f" [大小] {file_size} 字节") - if not is_binary: - self._strip_debug_sections(exe_path) - else: - print(f" [错误] 链接失败: {result.stderr.strip()}") - print(f"\n[编译终止] 链接失败,立即终止编译。") - sys.exit(1) - except FileNotFoundError: - print(f" [错误] 找不到链接器: {self.linker_cmd}") - print(f"\n[编译终止] 找不到链接器,立即终止编译。") - sys.exit(1) - except Exception as e: - print(f" [错误] {e}") - print(f"\n[编译终止] 链接异常,立即终止编译。") - sys.exit(1) - - -def save_sha1_map(temp_dir: str, sha1_map: dict[str, str]): - """将 SHA1 映射表保存到文件""" - map_path = os.path.join(temp_dir, '_sha1_map.txt') - with open(map_path, 'w', encoding='utf-8') as f: - for sha1, rel in sorted(sha1_map.items()): - f.write(f"{sha1}:{rel}\n") - - -def load_sha1_map(temp_dir: str) -> dict[str, str]: - """从文件加载 SHA1 映射表""" - map_path = os.path.join(temp_dir, '_sha1_map.txt') - result = {} - if os.path.exists(map_path): - with open(map_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if ':' in line: - sha1, rel = line.split(':', 1) - result[sha1] = rel - return result - - -def load_project_config(project_file: str) -> dict: - """从 project.json 加载配置""" - import json - with open(project_file, 'r', encoding='utf-8') as f: - return json.load(f) - - -def resolve_paths(config: dict, project_file: str) -> dict: - """将配置中的相对路径转换为绝对路径""" - project_dir = os.path.dirname(os.path.abspath(project_file)) - result = dict(config) - - def resolve(p): - if p is None: - return None - if os.path.isabs(p): - return p - return os.path.normpath(os.path.join(project_dir, p)) - - if 'source_dir' in result: - result['source_dir'] = resolve(result.get('source_dir')) - elif 'sources' in result: - resolved_sources = [] - for src in result['sources']: - if '*' in src or '?' in src: - import glob as glob_module - for matched in glob_module.glob(os.path.join(project_dir, src), recursive=True): - if os.path.isfile(matched): - resolved_sources.append(matched) - else: - resolved_sources.append(resolve(src)) - result['sources'] = [s for s in resolved_sources if os.path.isfile(s)] - - result['temp_dir'] = resolve(config.get('temp_dir')) - result['output_dir'] = resolve(config.get('output_dir')) - - if 'includes' in result: - result['includes'] = [resolve(inc) for inc in result['includes']] - - result['_project_dir'] = project_dir - return result - - -def main(): - import argparse - parser = argparse.ArgumentParser( - description='TransPyC 工程翻译器 - 基于 project.json 的两阶段翻译', - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=''' -示例: - # 从 project.json 读取配置并执行(默认查找当前目录) - python ProjectTrans.py - - # 指定 project.json 文件 - python ProjectTrans.py --project ./TestProject/project.json - - # 使用命令行参数覆盖 project.json 配置 - python ProjectTrans.py --src ./src --temp ./decl --output ./out --phase all - - # 仅运行阶段一 - python ProjectTrans.py --phase 1 - - # 仅运行阶段二 - python ProjectTrans.py --phase 2 - - # 清理临时目录 - python ProjectTrans.py --clean -''' - ) - parser.add_argument('--project', help='project.json 路径(默认查找当前目录)') - parser.add_argument('--src', help='源文件目录(覆盖 project.json)') - parser.add_argument('--temp', help='声明接口临时目录(覆盖 project.json)') - parser.add_argument('--output', help='输出目录(覆盖 project.json)') - parser.add_argument('--phase', choices=['1', '2', 'all'], help='阶段: 1=生成声明, 2=翻译+编译, all=全部') - parser.add_argument('--cc', help='LLVM 编译器命令(覆盖 project.json)') - parser.add_argument('--clean', action='store_true', help='清理 output 和 temp 目录') - - args = parser.parse_args() - - project_file = args.project - if not project_file: - candidates = ['project.json', './project.json'] - for c in candidates: - if os.path.exists(c): - project_file = c - break - - if project_file and os.path.exists(project_file): - print(f"[配置] 读取: {project_file}") - config = load_project_config(project_file) - project_dir = os.path.dirname(os.path.abspath(project_file)) - print(f"[配置] 项目目录: {project_dir}") - else: - print("[错误] 未找到 project.json,请使用 --project 指定") - sys.exit(1) - - resolved = resolve_paths(config, project_file) - src = args.src or resolved.get('source_dir') or resolved.get('sources') - temp_dir = args.temp or resolved.get('temp_dir') - output_dir = args.output or resolved.get('output_dir') - phase = args.phase or 'all' - cc_cmd = args.cc or resolved.get('compiler', {}).get('cmd', 'llc') - cc_flags = resolved.get('compiler', {}).get('flags', ['-filetype=obj']) - slice_level = resolved.get('options', {}).get('slice_level', 3) - project_include_dirs = resolved.get('includes', []) - target_triple = resolved.get('target', {}).get('triple') - target_datalayout = resolved.get('target', {}).get('datalayout') - - if isinstance(src, list): - if len(src) == 1 and os.path.isdir(src[0]): - src = src[0] - else: - src = src[0] if len(src) == 1 else os.path.dirname(os.path.commonpath(src)) if all(os.path.exists(p) for p in src) else src[0] - - print(f"[配置] 源目录: {src}") - print(f"[配置] 临时目录: {temp_dir}") - print(f"[配置] 输出目录: {output_dir}") - print(f"[配置] 阶段: {phase}") - print(f"[配置] 编译器: {cc_cmd} {' '.join(cc_flags)}") - if target_triple: - print(f"[配置] 目标三元组: {target_triple}") - if target_datalayout: - print(f"[配置] 数据布局: {target_datalayout}") - - if args.clean: - if output_dir and os.path.exists(output_dir): - for f in os.listdir(output_dir): - fpath = os.path.join(output_dir, f) - try: - if os.path.isfile(fpath) or os.path.islink(fpath): - os.remove(fpath) - elif os.path.isdir(fpath): - shutil.rmtree(fpath, ignore_errors=True) - except: - pass - print(f"[清理] output: 已清空 {output_dir}") - if temp_dir and os.path.exists(temp_dir): - for f in os.listdir(temp_dir): - fpath = os.path.join(temp_dir, f) - try: - if os.path.isfile(fpath) or os.path.islink(fpath): - os.remove(fpath) - elif os.path.isdir(fpath): - shutil.rmtree(fpath, ignore_errors=True) - except: - pass - print(f"[清理] temp: 已清空 {temp_dir}") - print("[清理] 完成") - if (not phase or phase == 'all') and not args.project: - return - - if phase in ('1', 'all'): - if isinstance(src, list): - print("[错误] 阶段一需要指定源目录,不支持文件列表") - sys.exit(1) - all_include_dirs = list(project_include_dirs) if project_include_dirs else [] - for d in Phase2Translator.INCLUDE_DIRS: - if os.path.isdir(d): - d = os.path.abspath(d) - if d not in [os.path.abspath(x) for x in all_include_dirs]: - all_include_dirs.append(d) - gen = Phase1Generator(src, temp_dir, include_dirs=all_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout) - gen.run() - save_sha1_map(temp_dir, gen.sha1_map) - - if phase in ('2', 'all'): - if not output_dir: - print("[错误] 阶段二需要指定 --output 目录") - sys.exit(1) - if not os.path.exists(temp_dir): - print(f"[错误] 声明目录不存在,请先运行阶段一: {temp_dir}") - sys.exit(1) - if isinstance(src, list): - print("[错误] 阶段二需要指定源目录,不支持文件列表") - sys.exit(1) - linker_cmd = resolved.get('linker', {}).get('cmd') - linker_flags = resolved.get('linker', {}).get('flags', []) - linker_output = resolved.get('linker', {}).get('output') - target_triple = resolved.get('target', {}).get('triple') - target_datalayout = resolved.get('target', {}).get('datalayout') - trans = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout) - trans.sha1_map = load_sha1_map(temp_dir) - trans.slice_level = slice_level - trans.run() +__all__ = [ + 'compute_sha1', '_check_annotation_for_export', 'sha1_file', + 'get_file_dependencies', 'find_reachable_files_from_entries', + 'topological_sort_files', 'Phase1Generator', 'DeclarationGenerator', + 'Phase2Translator', '_parallel_translate_worker', + 'save_sha1_map', 'Load_sha1_map', 'Load_project_config', 'resolve_paths', 'main' +] if __name__ == '__main__': main() diff --git a/StubGen.py b/StubGen.py index 823e842..57447dd 100644 --- a/StubGen.py +++ b/StubGen.py @@ -1,1337 +1,12 @@ -#!/usr/bin/env python3 -""" -StubGen - C/H/Py 文件到 Python 存根文件生成器(工程化版本) - -用法: - python StubGen.py -c config.json - python StubGen.py -i input.h -o output.py - python StubGen.py -d ./kernel -o ./kernel/include - -示例配置: - { - "InputDir": "./kernel", - "OutputDir": "./kernel/include", - "IncludePatterns": ["*.h", "*.c", "*.py"], - "ExcludePatterns": ["*_test.py"], - "PreserveStructure": true, - "GenerateGuards": true, - "TypeMappings": { - "custom_type": "t.CCustom" - } - } -""" - -import sys -import os -import re -import json -import ast -import argparse -import logging -from pathlib import Path -from typing import List, Dict, Optional, Set, Tuple -from dataclasses import dataclass, field - -sys.path.insert(0, os.path.dirname(__file__)) - -from lib.core.stub_generator import CHeaderParser, PythonStubGenerator, CTypeMapper - - -@dataclass -class StubGenConfig: - """存根生成器配置""" - InputDir: Optional[str] = None - OutputDir: str = "./stubs" - InputFiles: List[str] = field(default_factory=list) - IncludePatterns: List[str] = field(default_factory=lambda: ["*.h", "*.c", "*.py"]) - ExcludePatterns: List[str] = field(default_factory=list) - TypeMappings: Dict[str, str] = field(default_factory=dict) - PreserveStructure: bool = True # 保持目录结构 - GenerateGuards: bool = True # 生成宏守卫 - verbose: bool = False - DryRun: bool = False - - @classmethod - def from_dict(cls, data: Dict) -> 'StubGenConfig': - """从字典创建配置""" - return cls( - InputDir=data.get('InputDir'), - OutputDir=data.get('OutputDir', './stubs'), - InputFiles=data.get('InputFiles', []), - IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.py']), - ExcludePatterns=data.get('ExcludePatterns', []), - TypeMappings=data.get('TypeMappings', {}), - PreserveStructure=data.get('PreserveStructure', True), - GenerateGuards=data.get('GenerateGuards', True), - verbose=data.get('verbose', False), - DryRun=data.get('DryRun', False), - ) - - @classmethod - def from_file(cls, FilePath: str) -> 'StubGenConfig': - """从 JSON 文件加载配置""" - with open(FilePath, 'r', encoding='utf-8') as f: - data = json.load(f) - return cls.from_dict(data) - - -class PythonToStubConverter: - """将 Python 文件转换为存根格式""" - - # __include 别名映射表 {alias: ModuleName} - IncludeAliasMap: Dict[str, str] = {} - - # 变量排除列表 - 匹配这些模式的变量不会被添加到存根文件 - VarExcludeList: List[str] = [] - - # 宏排除列表 - 匹配这些模式的宏不会被添加到存根文件 - MacroExcludeList: List[str] = [] - - @classmethod - def SetIncludeAliasMap(cls, alias_map: Dict[str, str]): - """设置 __include 别名映射表""" - cls.IncludeAliasMap = alias_map - - @classmethod - def SetVarExcludeList(cls, exclude_list: List[str]): - """设置变量排除列表""" - cls.VarExcludeList = exclude_list - - @classmethod - def SetMacroExcludeList(cls, exclude_list: List[str]): - """设置宏排除列表""" - cls.MacroExcludeList = exclude_list - - @classmethod - def _ShouldExcludeVar(cls, VarName: str) -> bool: - """检查变量是否应该被排除""" - import fnmatch - for pattern in cls.VarExcludeList: - if fnmatch.fnmatch(VarName, pattern): - return True - return False - - @classmethod - def _ShouldExcludeMacro(cls, MacroName: str) -> bool: - """检查宏是否应该被排除""" - import fnmatch - for pattern in cls.MacroExcludeList: - if fnmatch.fnmatch(MacroName, pattern): - return True - return False - - @staticmethod - def convert(PyContent: str, ModuleName: str) -> str: - """将 Python 代码转换为存根格式""" - lines = PyContent.split('\n') - StubLines = [] - - # 添加文件头 - StubLines.append('"""') - StubLines.append(f'Auto-generated Python stub file from {ModuleName}.py') - StubLines.append(f'Module: {ModuleName}') - StubLines.append('"""') - StubLines.append('') - - # 解析 Python 代码,检查是否已经导入了 t 和 c - import ast - HasImportT = False - HasImportC = False - try: - tree = ast.parse(PyContent) - for node in tree.body: - if isinstance(node, ast.Import): - for alias in node.names: - if alias.name == 't': - HasImportT = True - elif alias.name == 'c': - HasImportC = True - except: - pass - - # 添加默认导入(如果源代码中没有) - if not HasImportT: - StubLines.append('import t') - if not HasImportC: - StubLines.append('import c') - if not HasImportT or not HasImportC: - StubLines.append('') - - # 添加 c.CPragma("once") - # StubLines.append('c.CPragma("once")') - StubLines.append('') - - # 生成文件级别宏守卫名称 - #FileGuardName = f'__{ModuleName.upper()}_DEFINE__' - - # 添加文件开头宏守卫 - #StubLines.append(f'c.CIfndef({FileGuardName})') - #StubLines.append(f'{FileGuardName}: t.CDefine') - #StubLines.append('') - - # 解析 Python 代码,提取类型定义 - try: - tree = ast.parse(PyContent) - - # 第一遍扫描:收集 Postdefinition 变量 - PostdefVars = {} # {ClassName: [(VarName, TypeStr, node), ...]} - for node in tree.body: - if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - TypeStr = PythonToStubConverter._GetTypeString(node.annotation) - # 检查是否是 Postdefinition 类型 - if 't.Postdefinition' in TypeStr: - # 提取引用的类名 - ClassName = PythonToStubConverter._ExtractPostdefClass(node.annotation) - if ClassName: - if ClassName not in PostdefVars: - PostdefVars[ClassName] = [] - PostdefVars[ClassName].append((node.target.id, TypeStr, node)) - - # 按原始顺序处理节点,保持代码的原始顺序 - PrevType = None # 记录前一个节点的类型 - - for node in tree.body: - CurrentType = None - - if isinstance(node, ast.ClassDef): - CurrentType = 'class' - # 如果前一个不是类,添加空行分隔 - if PrevType is not None and PrevType != 'class': - StubLines.append('') - # 检查是否有对应的 Postdefinition 变量 - ClassPostdefs = PostdefVars.get(node.name, []) - ClassLines = PythonToStubConverter._ConvertClass( - node, SourceLines=lines, PostdefVars=ClassPostdefs - ) - StubLines.extend(ClassLines) - elif isinstance(node, ast.FunctionDef): - CurrentType = 'function' - # 如果前一个是类或者是第一个函数,添加空行分隔 - if PrevType == 'class' or (PrevType is not None and PrevType != 'function'): - StubLines.append('') - FuncLines = PythonToStubConverter._ConvertFunction(node, SourceLines=lines) - StubLines.extend(FuncLines) - StubLines.append('') # 函数后空行 - elif isinstance(node, ast.AnnAssign): - CurrentType = 'variable' - # 跳过 Postdefinition 变量(已经在类中处理) - TypeStr = PythonToStubConverter._GetTypeString(node.annotation) - if 't.Postdefinition' in TypeStr: - continue - # 检查是否带有 t.CStatic 标志,如果有则不排除 - HasStatic = 't.CStatic' in TypeStr - # 检查变量是否应该被排除 - ShouldExclude = False - if isinstance(node.target, ast.Name) and not HasStatic: - VarName = node.target.id - if PythonToStubConverter._ShouldExcludeVar(VarName): - ShouldExclude = True - if ShouldExclude: - continue - # 如果前一个不是变量,添加空行分隔 - if PrevType is not None and PrevType != 'variable': - StubLines.append('') - VarLines = PythonToStubConverter._ConvertVariable(node, SourceLines=lines) - # 移除多余的空行 - VarLines = [line for line in VarLines if line.strip()] - StubLines.extend(VarLines) - elif isinstance(node, ast.Import): - # 处理导入语句 - CurrentType = 'import' - ImportStr = PythonToStubConverter._GetImportString(node, SourceLines=lines) - if ImportStr: - if PrevType is not None and PrevType != 'import': - StubLines.append('') - StubLines.append(ImportStr) - elif isinstance(node, ast.Assign): - CurrentType = 'variable' - # 处理模块级别的全局变量(无类型标注) - if PrevType is not None and PrevType != 'variable': - StubLines.append('') - AssignLines = PythonToStubConverter._ConvertGlobalAssign(node) - StubLines.extend(AssignLines) - elif isinstance(node, ast.ImportFrom): - # 处理 from ... import ... 语句 - CurrentType = 'import' - ImportStr = PythonToStubConverter._GetImportFromString(node, SourceLines=lines) - if ImportStr: - if PrevType is not None and PrevType != 'import': - StubLines.append('') - StubLines.append(ImportStr) - elif isinstance(node, ast.Expr): - # 处理模块级别的宏调用,如 c.CIf(...), c.CEndif() - ExprStr = PythonToStubConverter._GetExprString(node.value) - if ExprStr: - CurrentType = 'macro' - StubLines.append(ExprStr) - StubLines.append('') # 宏后空行 - elif isinstance(node, ast.If): - # 处理模块级别的 if 宏条件,如 if c.CIf(FF_MULTI_PARTITION): - IfStr = PythonToStubConverter._GetModuleIfMacroString(node) - if IfStr: - CurrentType = 'macro' - StubLines.append(IfStr) - StubLines.append('') # 宏后空行 - - if CurrentType: - PrevType = CurrentType - - # 添加文件结尾宏守卫 - #StubLines.append('') - #StubLines.append('c.CEndif()') - - except SyntaxError as e: - # 如果解析失败,添加注释说明 - StubLines.append(f'# Warning: Failed to parse Python code: {e}') - StubLines.append('# Original content:') - StubLines.append('"""') - StubLines.append(PyContent[:1000]) # 只显示前1000字符 - StubLines.append('"""') - - return '\n'.join(StubLines) - - @staticmethod - def _ConvertClass(node: ast.ClassDef, SourceLines: List[str] = None, PostdefVars: List[Tuple[str, str, ast.AnnAssign]] = None, indent: int = 0) -> List[str]: - """转换类定义 - - Args: - node: 类定义节点 - SourceLines: 源代码行列表 - PostdefVars: Postdefinition 变量列表 [(VarName, TypeStr, node), ...] - indent: 缩进级别(用于嵌套类) - """ - lines = [] - PostdefVars = PostdefVars or [] - IndentStr = ' ' * indent - - # 处理类装饰器 - for decorator in node.decorator_list: - DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) - if DecoratorStr: - lines.append(f'{IndentStr}@{DecoratorStr}') - - # 检查是否是结构体、联合体或枚举 - BaseNames = [base.attr if isinstance(base, ast.Attribute) else base.id - for base in node.bases - if isinstance(base, (ast.Name, ast.Attribute))] - - # 保留原始基类 - if node.bases: - BaseStrs = [] - for base in node.bases: - if isinstance(base, ast.Name): - BaseStrs.append(base.id) - elif isinstance(base, ast.Attribute): - BaseStrs.append(f'{base.value.id}.{base.attr}') - elif isinstance(base, ast.Subscript): - # 处理泛型类型,如 memory_block_t[MAX_ORDER + 1] - BaseStrs.append(PythonToStubConverter._GetTypeString(base)) - ClassTypeParamStr = '' - if hasattr(node, 'type_params') and node.type_params: - param_names = [tp.name for tp in node.type_params] - ClassTypeParamStr = f'[{", ".join(param_names)}]' - if BaseStrs: - lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}({", ".join(BaseStrs)}):') - else: - lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}:') - else: - ClassTypeParamStr = '' - if hasattr(node, 'type_params') and node.type_params: - param_names = [tp.name for tp in node.type_params] - ClassTypeParamStr = f'[{", ".join(param_names)}]' - lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}:') - - # 处理类成员 - HasMembers = False - seen_member_names = set() - for item in node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - seen_member_names.add(item.target.id) - init_members = [] - for item in node.body: - if isinstance(item, ast.FunctionDef) and item.name == '__init__': - for stmt in item.body: - if (isinstance(stmt, ast.AnnAssign) - and isinstance(stmt.target, ast.Attribute) - and isinstance(stmt.target.value, ast.Name) - and stmt.target.value.id == 'self'): - init_members.append(stmt) - untyped_self_members = [] - for m_name in [m.target.attr for m in init_members if isinstance(m.target, ast.Attribute)]: - seen_member_names.add(m_name) - for item in node.body: - if isinstance(item, ast.FunctionDef): - for stmt in item.body: - if (isinstance(stmt, ast.Assign) - and len(stmt.targets) == 1 - and isinstance(stmt.targets[0], ast.Attribute) - and isinstance(stmt.targets[0].value, ast.Name) - and stmt.targets[0].value.id == 'self'): - attr_name = stmt.targets[0].attr - if attr_name not in seen_member_names: - seen_member_names.add(attr_name) - untyped_self_members.append(stmt) - for item in list(node.body) + init_members + untyped_self_members: - if isinstance(item, ast.Assign): - if (len(item.targets) == 1 - and isinstance(item.targets[0], ast.Attribute) - and isinstance(item.targets[0].value, ast.Name) - and item.targets[0].value.id == 'self'): - HasMembers = True - MemberIndent = IndentStr + ' ' - attr_name = item.targets[0].attr - if attr_name in seen_member_names: - continue - InferredType = 'int' - if item.value and isinstance(item.value, ast.Constant): - if isinstance(item.value.value, float): - InferredType = 'float' - elif isinstance(item.value.value, bool): - InferredType = 'bool' - elif isinstance(item.value.value, str): - InferredType = 'str' - lines.append(f'{MemberIndent}{attr_name}: {InferredType}') - else: - HasMembers = True - MemberIndent = IndentStr + ' ' - if SourceLines and hasattr(item, 'lineno'): - StartLine = item.lineno - 1 - EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 - for i in range(StartLine, min(EndLine, len(SourceLines))): - lines.append(MemberIndent + SourceLines[i].lstrip()) - elif isinstance(item, ast.AnnAssign): - HasMembers = True - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) - MemberIndent = IndentStr + ' ' - # 检查是否是宏变量(类型包含 t.CDefine) - if 't.CDefine' in TypeStr: - # 检查宏变量是否应该被排除 - if isinstance(item.target, ast.Name): - MacroName = item.target.id - if PythonToStubConverter._ShouldExcludeMacro(MacroName): - continue # 跳过该宏 - # 宏变量保持原样(包括赋值) - if SourceLines and hasattr(item, 'lineno'): - StartLine = item.lineno - 1 - EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 - for i in range(StartLine, min(EndLine, len(SourceLines))): - lines.append(MemberIndent + SourceLines[i].lstrip()) - else: - lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') - else: - if isinstance(item.target, ast.Attribute): - MemberName = item.target.attr - else: - MemberName = item.target.id - FinalTypeStr = TypeStr - if (isinstance(item.annotation, ast.Subscript) - and isinstance(item.annotation.value, ast.Name) - and item.annotation.value.id == 'list'): - slice_node = item.annotation.slice - has_size = False - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - count_node = slice_node.elts[1] - if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0: - has_size = True - else: - try: - count_expr = ast.unparse(count_node) - except Exception: - count_expr = '' - if count_expr and count_expr != 'None': - has_size = True - elem_type_str = PythonToStubConverter._GetTypeString(slice_node.elts[0]) - FinalTypeStr = f'list[{elem_type_str}, {count_expr}]' - if not has_size: - elem_type_str = PythonToStubConverter._GetTypeString(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0]) - init_len = 0 - if item.value is not None: - if isinstance(item.value, ast.List): - init_len = len(item.value.elts) - elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): - init_len = len(item.value.value) + 1 - if init_len > 0: - FinalTypeStr = f'list[{elem_type_str}, {init_len}]' - else: - FinalTypeStr = f'list[{elem_type_str}, None]' - lines.append(f'{MemberIndent}{MemberName}: {FinalTypeStr}') - elif isinstance(item, ast.FunctionDef): - HasMembers = True - FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name) - lines.extend(FuncStub) - elif isinstance(item, ast.Expr): - # 处理宏调用,如 c.CIf(...), c.CEndif(), c.CElif(), c.CElse() - ExprStr = PythonToStubConverter._GetExprString(item.value) - if ExprStr: - lines.append(f'{IndentStr} {ExprStr}') - elif isinstance(item, ast.If): - # 处理 if c.CIf(...): 形式的宏条件 - IfStr = PythonToStubConverter._get_if_macro_string(item, indent=indent+1) - if IfStr: - lines.append(IfStr) - elif isinstance(item, ast.ClassDef): - # 处理嵌套类 - HasMembers = True - NestedClassLines = PythonToStubConverter._ConvertClass(item, SourceLines=SourceLines, PostdefVars=[], indent=indent+1) - # 移除嵌套类的宏守卫(因为已经在父类的宏守卫内) - FilteredLines = [] - for line in NestedClassLines: - # 跳过宏守卫相关行 - if line.strip().startswith('c.CIfndef(') or line.strip().startswith('c.CEndif()'): - continue - if ': t.CDefine' in line and '__' in line: - continue - FilteredLines.append(line) - lines.extend(FilteredLines) - - if not HasMembers: - lines.append(f'{IndentStr} pass') - - # 添加 Postdefinition 变量 - if PostdefVars: - lines.append('') - for VarName, TypeStr, _ in PostdefVars: - lines.append(f'{VarName}: {TypeStr}') - - return lines - - @staticmethod - def _ConvertFunction(node: ast.FunctionDef, indent: int = 0, SourceLines: List[str] = None, class_name: str = None) -> List[str]: - """转换函数定义""" - lines = [] - IndentStr = ' ' * indent - - # 检查是否是宏函数(返回类型包含 t.CDefine) - is_macro_func = False - if node.returns: - ReturnType = PythonToStubConverter._GetTypeString(node.returns) - if 't.CDefine' in ReturnType: - is_macro_func = True - - # 如果是宏函数,检查是否应该被排除 - if is_macro_func: - if PythonToStubConverter._ShouldExcludeMacro(node.name): - return lines # 返回空列表,排除该宏 - - # 保持原样(包括代码块) - if SourceLines: - StartLine = node.lineno - 1 - EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 - for i in range(StartLine, min(EndLine, len(SourceLines))): - lines.append(SourceLines[i]) - if lines and lines[-1].strip() and not lines[-1].rstrip().endswith(':'): - pass - else: - lines.append(f'{IndentStr} pass') - return lines - - # 处理函数装饰器 - for decorator in node.decorator_list: - DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) - if DecoratorStr: - lines.append(f'{IndentStr}@{DecoratorStr}') - - # 构建参数列表 - params = [] - for arg_idx, arg in enumerate(node.args.args): - ArgName = arg.arg - if arg.annotation: - TypeStr = PythonToStubConverter._GetTypeString(arg.annotation) - params.append(f'{ArgName}: {TypeStr}') - elif class_name and arg_idx == 0 and ArgName == 'self': - params.append(f'self: {class_name}') - else: - params.append(ArgName) - - # 处理 *args - if node.args.vararg: - ArgName = node.args.vararg.arg - if node.args.vararg.annotation: - TypeStr = PythonToStubConverter._GetTypeString(node.args.vararg.annotation) - params.append(f'*{ArgName}: {TypeStr}') - else: - params.append(f'*{ArgName}') - - # 处理 **kwargs - if node.args.kwarg: - ArgName = node.args.kwarg.arg - if node.args.kwarg.annotation: - TypeStr = PythonToStubConverter._GetTypeString(node.args.kwarg.annotation) - params.append(f'**{ArgName}: {TypeStr}') - else: - params.append(f'**{ArgName}') - - ParamStr = ', '.join(params) - - # 返回类型 - 保持原始类型(不添加t.State) - if node.returns: - ReturnType = PythonToStubConverter._GetTypeString(node.returns) - else: - ReturnType = 't.CInt' - - TypeParamStr = '' - if hasattr(node, 'type_params') and node.type_params: - param_names = [tp.name for tp in node.type_params] - TypeParamStr = f'[{", ".join(param_names)}]' - - lines.append(f'{IndentStr}def {node.name}{TypeParamStr}({ParamStr}) -> {ReturnType}: pass') - return lines - - @staticmethod - def _ConvertVariable(node: ast.AnnAssign, SourceLines: List[str] = None) -> List[str]: - """转换变量定义""" - lines = [] - if isinstance(node.target, ast.Name): - VarName = node.target.id - TypeStr = PythonToStubConverter._GetTypeString(node.annotation) - # 检查是否是宏变量(类型包含 t.CDefine) - if 't.CDefine' in TypeStr: - # 检查宏变量是否应该被排除 - if PythonToStubConverter._ShouldExcludeMacro(VarName): - return lines # 返回空列表,排除该宏 - # 宏变量保持原样(包括赋值) - if SourceLines and hasattr(node, 'lineno'): - StartLine = node.lineno - 1 - EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 - for i in range(StartLine, min(EndLine, len(SourceLines))): - lines.append(SourceLines[i]) - else: - lines.append(f'{VarName}: {TypeStr}') - return lines - # 非宏变量:不加 t.State - # 含有 typedef 的变量不加 extern,普通变量需要加 extern - has_typedef = 't.CTypedef' in TypeStr or 'CTypedef' in TypeStr - if has_typedef and node.value is not None: - ValueTypeStr = PythonToStubConverter._GetTypeString(node.value) - lines.append(f'{VarName}: {TypeStr} = {ValueTypeStr}') - else: - if not has_typedef and 't.CExtern' not in TypeStr and 't.CStatic' not in TypeStr: - TypeStr = f't.CExtern | {TypeStr}' - lines.append(f'{VarName}: {TypeStr}') - return lines - - @staticmethod - def _ConvertGlobalAssign(node: ast.Assign) -> List[str]: - """转换模块级别的全局变量(无类型标注)""" - lines = [] - if not node.targets or not isinstance(node.targets[0], ast.Name): - return lines - - VarName = node.targets[0].id - - # 跳过私有变量(以下划线开头) - if VarName.startswith('_'): - return lines - - # 从值推断类型 - inferred_type = PythonToStubConverter._InferTypeFromValue(node.value) - if inferred_type: - lines.append(f'{VarName}: {inferred_type}') - else: - lines.append(f'{VarName}: t.CInt') - - return lines - - @staticmethod - def _InferTypeFromValue(value: ast.AST) -> str: - """从值推断 C 类型""" - if isinstance(value, ast.Constant): - if isinstance(value.value, int): - return 't.CInt' - elif isinstance(value.value, float): - return 't.CDouble' - elif isinstance(value.value, str): - return 't.CCharPtr' - elif isinstance(value.value, bool): - return 't.CInt' - elif isinstance(value, ast.List): - return 't.CVoidPtr' - elif isinstance(value, ast.Dict): - return 't.CVoidPtr' - elif isinstance(value, ast.Name): - return 't.CInt' - elif isinstance(value, ast.BinOp): - left_type = PythonToStubConverter._InferTypeFromValue(value.left) - if left_type: - return left_type - return 't.CInt' - elif isinstance(value, ast.Call): - # 函数调用返回值,假设为指针类型 - if isinstance(value.func, ast.Name): - func_name = value.func.id - if func_name == 'malloc': - return 't.CVoidPtr' - elif func_name in ('ctypes.cast', 'cast'): - return 't.CVoidPtr' - return 't.CVoidPtr' - return None - - @staticmethod - def _GetTypeString(annotation: ast.AST) -> str: - """获取类型字符串""" - if isinstance(annotation, ast.Name): - return annotation.id - elif isinstance(annotation, ast.Attribute): - if isinstance(annotation.value, ast.Name): - return f'{annotation.value.id}.{annotation.attr}' - else: - # 处理嵌套属性访问,如 t.attr.packed - ParentStr = PythonToStubConverter._GetTypeString(annotation.value) - return f'{ParentStr}.{annotation.attr}' - elif isinstance(annotation, ast.Subscript): - base = PythonToStubConverter._GetTypeString(annotation.value) - if isinstance(annotation.slice, ast.Tuple): - slice_strs = [PythonToStubConverter._GetTypeString(e) for e in annotation.slice.elts] - SliceStr = ', '.join(slice_strs) - else: - SliceStr = PythonToStubConverter._GetTypeString(annotation.slice) - return f'{base}[{SliceStr}]' - elif isinstance(annotation, ast.BinOp): - # 处理 BinOp,如 t.CExtern | fd_table.__set_default__(...) - left = annotation.left - right = annotation.right - - # 检查右侧是否是 __set_default__ 调用 - if isinstance(right, ast.Call) and isinstance(right.func, ast.Attribute) and right.func.attr in ('__set_default__', '__set_default'): - # 去除 __set_default__,保留左侧,右侧替换为函数名部分 - LeftStr = PythonToStubConverter._GetTypeString(left) - RightStr = PythonToStubConverter._GetTypeString(right.func.value) - if isinstance(annotation.op, ast.BitOr): - return f'{LeftStr} | {RightStr}' - - LeftStr = PythonToStubConverter._GetTypeString(left) - RightStr = PythonToStubConverter._GetTypeString(right) - if isinstance(annotation.op, ast.BitOr): - return f'{LeftStr} | {RightStr}' - elif isinstance(annotation.op, ast.Add): - return f'{LeftStr} + {RightStr}' - elif isinstance(annotation.op, ast.Sub): - return f'{LeftStr} - {RightStr}' - elif isinstance(annotation.op, ast.Mult): - return f'{LeftStr} * {RightStr}' - elif isinstance(annotation.op, ast.Div): - return f'{LeftStr} / {RightStr}' - elif isinstance(annotation.op, ast.Mod): - return f'{LeftStr} % {RightStr}' - elif isinstance(annotation, ast.UnaryOp): - if isinstance(annotation.op, ast.Not): - operand = PythonToStubConverter._GetTypeString(annotation.operand) - return f'not {operand}' - elif isinstance(annotation.op, ast.Invert): - operand = PythonToStubConverter._GetTypeString(annotation.operand) - return f'~{operand}' - elif isinstance(annotation.op, ast.USub): - operand = PythonToStubConverter._GetTypeString(annotation.operand) - return f'-{operand}' - elif isinstance(annotation, ast.Compare): - # 处理比较操作,如 FF_MAX_SS != FF_MIN_SS - left = PythonToStubConverter._GetTypeString(annotation.left) - comparators = [PythonToStubConverter._GetTypeString(c) for c in annotation.comparators] - ops = [] - for op in annotation.ops: - if isinstance(op, ast.Eq): - ops.append('==') - elif isinstance(op, ast.NotEq): - ops.append('!=') - elif isinstance(op, ast.Lt): - ops.append('<') - elif isinstance(op, ast.LtE): - ops.append('<=') - elif isinstance(op, ast.Gt): - ops.append('>') - elif isinstance(op, ast.GtE): - ops.append('>=') - else: - ops.append('?') - result = left - for i, op in enumerate(ops): - result += f' {op} {comparators[i]}' - return result - elif isinstance(annotation, ast.Constant): - return repr(annotation.value) - elif isinstance(annotation, ast.Index): - return PythonToStubConverter._GetTypeString(annotation.value) - elif isinstance(annotation, ast.List): - # 处理列表,如 [MAX_FILE_DESCRIPTORS] - elements = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] - return f'[{", ".join(elements)}]' - elif isinstance(annotation, ast.Call): - # 处理函数调用形式的类型注解,如 t.Postdefinition(xxa) 或 callable(t.CVoid, app_id = t.CInt) - # 如果是 __set_default__ 调用,只返回函数名部分 - if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'): - return PythonToStubConverter._GetTypeString(annotation.func.value) - - FuncStr = PythonToStubConverter._GetTypeString(annotation.func) - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in annotation.args]) - # 处理关键字参数 - keywords_str = ', '.join([f'{kw.arg} = {PythonToStubConverter._GetTypeString(kw.value)}' for kw in annotation.keywords]) - # 合并位置参数和关键字参数 - if ArgsStr and keywords_str: - return f'{FuncStr}({ArgsStr}, {keywords_str})' - elif keywords_str: - return f'{FuncStr}({keywords_str})' - else: - return f'{FuncStr}({ArgsStr})' - return 't.CVoid' - - @staticmethod - def _ExtractPostdefClass(annotation: ast.AST) -> Optional[str]: - """从 Postdefinition 类型注解中提取类名 - - 例如:t.Postdefinition(__buddy_system) -> '__buddy_system' - t.Postdefinition(xxx) | t.CTypedef -> 'xxx' - """ - # 处理 BinOp (如: t.Postdefinition(xxx) | t.CTypedef) - if isinstance(annotation, ast.BinOp): - # 递归检查左操作数 - left_result = PythonToStubConverter._ExtractPostdefClass(annotation.left) - if left_result: - return left_result - # 递归检查右操作数 - right_result = PythonToStubConverter._ExtractPostdefClass(annotation.right) - if right_result: - return right_result - return None - - # 处理函数调用 (如: t.Postdefinition(__buddy_system)) - if isinstance(annotation, ast.Call): - FuncStr = PythonToStubConverter._GetTypeString(annotation.func) - if FuncStr == 't.Postdefinition' and annotation.args: - # 提取第一个参数 - first_arg = annotation.args[0] - if isinstance(first_arg, ast.Name): - return first_arg.id - elif isinstance(first_arg, ast.Attribute): - return f'{first_arg.value.id}.{first_arg.attr}' - - return None - - @staticmethod - def _GetImportString(node: ast.Import, SourceLines: List[str] = None) -> str: - """获取导入语句字符串""" - parts = [] - IncludeAliasMap = PythonToStubConverter.IncludeAliasMap - - for alias in node.names: - ModuleName = alias.name - # 检查是否是 __include.xxx 格式的导入 - if ModuleName.startswith('__include.'): - # 提取别名(xxx 部分) - SubModule = ModuleName[len('__include.'):] - if SubModule in IncludeAliasMap: - # 替换为实际模块路径 - RealModule = IncludeAliasMap[SubModule] - if alias.asname: - parts.append(f'{RealModule} as {alias.asname}') - else: - parts.append(f'{RealModule} as {SubModule}') - else: - # 不在映射表中,保持原样 - if alias.asname: - parts.append(f'{ModuleName} as {alias.asname}') - else: - parts.append(ModuleName) - else: - if alias.asname: - parts.append(f'{alias.name} as {alias.asname}') - else: - parts.append(alias.name) - - result = f'import {", ".join(parts)}' - - # 提取并保留注释 - if SourceLines and hasattr(node, 'lineno'): - LineIdx = node.lineno - 1 - if 0 <= LineIdx < len(SourceLines): - line = SourceLines[LineIdx] - CommentMatch = re.search(r'#.*$', line) - if CommentMatch: - result += ' ' + CommentMatch.group(0) - - return result - - @staticmethod - def _GetImportFromString(node: ast.ImportFrom, SourceLines: List[str] = None) -> str: - """获取 from ... import ... 语句字符串""" - module = node.module or '' - parts = [] - IncludeAliasMap = PythonToStubConverter.IncludeAliasMap - - # 处理相对导入 (from . import xxx 或 from ..package import xxx) - if node.level > 0: - if module: - if node.level == 1: - full_module = f'.{module}' - else: - full_module = '.' * node.level + module - else: - full_module = '.' * node.level - for alias in node.names: - if alias.asname: - parts.append(f'{alias.name} as {alias.asname}') - else: - parts.append(alias.name) - return f'from {full_module} import {", ".join(parts)}' - - # 提取注释(在生成结果前获取) - comment = '' - if SourceLines and hasattr(node, 'lineno'): - LineIdx = node.lineno - 1 - if 0 <= LineIdx < len(SourceLines): - line = SourceLines[LineIdx] - CommentMatch = re.search(r'#.*$', line) - if CommentMatch: - comment = ' ' + CommentMatch.group(0) - - # 检查是否是 from __include import xxx 格式 - if module == '__include': - for alias in node.names: - name = alias.name - if name in IncludeAliasMap: - # 替换为实际模块路径 - RealModule = IncludeAliasMap[name] - if alias.asname: - parts.append(f'import {RealModule} as {alias.asname}{comment}') - else: - parts.append(f'import {RealModule} as {name}{comment}') - else: - # 不在映射表中,保持原样 - if alias.asname: - parts.append(f'from {module} import {name} as {alias.asname}{comment}') - else: - parts.append(f'from {module} import {name}{comment}') - return '\n'.join(parts) - - # 普通 from ... import ... 语句 - for alias in node.names: - if alias.asname: - parts.append(f'{alias.name} as {alias.asname}') - else: - parts.append(alias.name) - return f'from {module} import {", ".join(parts)}{comment}' - - @staticmethod - def _GetDecoratorString(decorator: ast.AST) -> str: - """获取装饰器字符串""" - if isinstance(decorator, ast.Name): - return decorator.id - elif isinstance(decorator, ast.Attribute): - if isinstance(decorator.value, ast.Name): - return f'{decorator.value.id}.{decorator.attr}' - return decorator.attr - elif isinstance(decorator, ast.Call): - # 处理带参数的装饰器,如 @c.Attribute(t.attr.packed) - FuncStr = PythonToStubConverter._GetDecoratorString(decorator.func) - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args]) - return f'{FuncStr}({ArgsStr})' - return '' - - @staticmethod - def _GetExprString(expr: ast.AST) -> str: - """获取表达式字符串(用于宏调用)""" - if isinstance(expr, ast.Call): - # 处理函数调用,如 c.CIf(...), c.CEndif(), c.CUndef(...), c.CPragma(...) - FuncStr = PythonToStubConverter._GetDecoratorString(expr.func) - if FuncStr and ('CIf' in FuncStr or 'CEndif' in FuncStr or 'CElif' in FuncStr or 'CElse' in FuncStr or 'CUndef' in FuncStr or 'CPragma' in FuncStr): - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args]) - return f'{FuncStr}({ArgsStr})' if ArgsStr else f'{FuncStr}()' - return '' - - @staticmethod - def _get_if_macro_string(node: ast.If, indent: int = 1) -> str: - """获取类内部的 if 宏字符串(如 if c.CIf(...):)""" - IndentStr = ' ' * indent - InnerIndent = ' ' * (indent + 1) - # 检查条件是否是宏调用 - if isinstance(node.test, ast.Call): - FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) - if FuncStr and 'CIf' in FuncStr: - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) - result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] - # 处理 if 体内的语句 - for item in node.body: - if isinstance(item, ast.AnnAssign): - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) - result.append(f'{InnerIndent}{item.target.id}: {TypeStr}') - elif isinstance(item, ast.Expr): - ExprStr = PythonToStubConverter._GetExprString(item.value) - if ExprStr: - result.append(f'{InnerIndent}{ExprStr}') - return '\n'.join(result) - return '' - - @staticmethod - def _GetModuleIfMacroString(node: ast.If) -> str: - """获取模块级别的 if 宏字符串(如 if c.CIf(FF_MULTI_PARTITION):)""" - return PythonToStubConverter._ProcessIfMacro(node, indent=0) - - @staticmethod - def _ProcessIfMacro(node: ast.If, indent: int = 0) -> str: - """处理 if 宏节点,支持 elif 和 else""" - IndentStr = ' ' * indent - - # 检查条件是否是宏调用 - if isinstance(node.test, ast.Call): - FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) - if FuncStr and 'CIf' in FuncStr: - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) - result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] - # 处理 if 体内的语句 - for item in node.body: - result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) - - # 处理 elif 和 else - current = node - while current.orelse: - if len(current.orelse) == 1 and isinstance(current.orelse[0], ast.If): - # elif 情况 - elif_node = current.orelse[0] - if isinstance(elif_node.test, ast.Call): - ElifFuncStr = PythonToStubConverter._GetDecoratorString(elif_node.test.func) - if ElifFuncStr and 'CIf' in ElifFuncStr: - ElifArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in elif_node.test.args]) - result.append(f'{IndentStr}elif {ElifFuncStr}({ElifArgsStr}):' if ElifArgsStr else f'{IndentStr}elif {ElifFuncStr}():') - for item in elif_node.body: - result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) - current = elif_node - continue - break - else: - # else 情况 - result.append(f'{IndentStr}else:') - for item in current.orelse: - result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) - break - - return '\n'.join(result) - return '' - - @staticmethod - def _ProcessMacroBodyItem(item: ast.AST, indent: int = 0) -> list: - """处理宏体内的单个语句""" - IndentStr = ' ' * indent - result = [] - - if isinstance(item, ast.ClassDef): - class_stub = PythonToStubConverter._ConvertClass(item) - for line in class_stub: - if line.strip(): - result.append(f'{IndentStr}{line}') - else: - result.append(line) - elif isinstance(item, ast.FunctionDef): - FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent) - result.extend(FuncStub) - elif isinstance(item, ast.AnnAssign): - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) - result.append(f'{IndentStr}{item.target.id}: {TypeStr}') - elif isinstance(item, ast.Expr): - ExprStr = PythonToStubConverter._GetExprString(item.value) - if ExprStr: - result.append(f'{IndentStr}{ExprStr}') - elif isinstance(item, ast.If): - # 处理嵌套的 if 宏 - NestedIf = PythonToStubConverter._ProcessIfMacro(item, indent=indent) - if NestedIf: - result.append(NestedIf) - - return result - - -class StubGen: - """存根生成器主类""" - - def __init__(self, config: StubGenConfig): - self.config = config - self.logger = self._SetupLogger() - self.GeneratedFiles: List[str] = [] - self.FailedFiles: List[str] = [] - - # 应用自定义类型映射 - if config.TypeMappings: - CTypeMapper.BASIC_TYPE_MAP.update(config.TypeMappings) - - def _SetupLogger(self) -> logging.Logger: - """设置日志""" - logger = logging.getLogger('StubGen') - logger.setLevel(logging.DEBUG if self.config.verbose else logging.INFO) - - if not logger.handlers: - handler = logging.StreamHandler(sys.stdout) - formatter = logging.Formatter( - '%(asctime)s - %(name)s - %(levelname)s - %(message)s', - datefmt='%H:%M:%S' - ) - handler.setFormatter(formatter) - logger.addHandler(handler) - - return logger - - def FindInputFiles(self) -> List[Tuple[str, str]]: - """查找输入文件,返回 (文件路径, 相对路径) 列表""" - files = [] - - # 添加显式指定的文件 - for FilePath in self.config.InputFiles: - if os.path.exists(FilePath): - RelPath = os.path.relpath(FilePath, self.config.InputDir or '.') - files.append((FilePath, RelPath)) - else: - self.logger.warning(f"Input file not found: {FilePath}") - - # 从输入目录查找 - if self.config.InputDir and os.path.exists(self.config.InputDir): - InputPath = Path(self.config.InputDir) - for pattern in self.config.IncludePatterns: - for FilePath in InputPath.rglob(pattern): - # 检查是否在排除列表中 - excluded = False - RelPath = os.path.relpath(str(FilePath), self.config.InputDir) - - for exclude_pattern in self.config.ExcludePatterns: - if FilePath.match(exclude_pattern) or RelPath == exclude_pattern: - excluded = True - break - - if not excluded: - files.append((str(FilePath), RelPath)) - - # 去重并保持顺序 - seen = set() - UniqueFiles = [] - for FilePath, RelPath in files: - key = FilePath - if key not in seen: - seen.add(key) - UniqueFiles.append((FilePath, RelPath)) - - return UniqueFiles - - def _GenerateGuardName(self, FilePath: str) -> str: - """生成宏守卫名称""" - # 获取文件名(不含扩展名) - BaseName = os.path.splitext(os.path.basename(FilePath))[0] - - # 转换为大写,替换特殊字符为下划线 - guard = re.sub(r'[^a-zA-Z0-9_]', '_', BaseName).upper() - guard = re.sub(r'_+', '_', guard) # 合并多个下划线 - guard = guard.strip('_') - - return f'{guard}_DEFINE_H' - - def _GetOutputPath(self, RelPath: str) -> str: - """获取输出文件路径""" - # 更改扩展名为 .pyi (Python stub file) - BaseName = os.path.splitext(RelPath)[0] - OutputRelPath = BaseName + '.pyi' - - # 构建完整输出路径 - if self.config.OutputDir: - OutputPath = os.path.join(self.config.OutputDir, OutputRelPath) - else: - OutputPath = OutputRelPath - - return OutputPath - - def GenerateStub(self, InputFile: str, RelPath: str) -> bool: - """生成单个存根文件""" - try: - self.logger.info(f"Processing: {InputFile}") - - # 确定输出文件路径 - OutputFile = self._GetOutputPath(RelPath) - - # 确保输出目录存在 - OutputDir = os.path.dirname(OutputFile) - if OutputDir and not os.path.exists(OutputDir): - if not self.config.DryRun: - os.makedirs(OutputDir, exist_ok=True) - self.logger.debug(f"Created directory: {OutputDir}") - - if self.config.DryRun: - self.logger.info(f"[DRY RUN] Would generate: {OutputFile}") - return True - - # 根据文件类型选择处理方式 - ext = os.path.splitext(InputFile)[1].lower() - - if ext in ['.h', '.c']: - # C 文件:使用 CHeaderParser - content = self._GenerateFromC(InputFile, RelPath) - elif ext == '.py': - # Python 文件:使用 PythonToStubConverter - content = self._GenerateFromPy(InputFile, RelPath) - else: - self.logger.warning(f"Unsupported file type: {ext}") - return False - - # 写入文件 - with open(OutputFile, 'w', encoding='utf-8') as f: - f.write(content) - - self.GeneratedFiles.append(OutputFile) - self.logger.info(f"Generated: {OutputFile}") - return True - - except Exception as e: - self.logger.error(f"Failed to process {InputFile}: {e}") - import traceback - traceback.print_exc() - self.FailedFiles.append(InputFile) - return False - - def _GenerateFromC(self, InputFile: str, RelPath: str) -> str: - """从 C 文件生成存根""" - parser = CHeaderParser() - parser.parse_file(InputFile) - - generator = PythonStubGenerator(parser) - ModuleName = os.path.splitext(os.path.basename(InputFile))[0] - content = generator.generate(ModuleName) - - # 添加宏守卫(如果需要) - if self.config.GenerateGuards: - guard_name = self._GenerateGuardName(InputFile) - guard_comment = f"\n# Guard: {guard_name}\n" - content = content + guard_comment - - return content - - def _GenerateFromPy(self, InputFile: str, RelPath: str) -> str: - """从 Python 文件生成存根""" - with open(InputFile, 'r', encoding='utf-8') as f: - PyContent = f.read() - - ModuleName = os.path.splitext(os.path.basename(InputFile))[0] - content = PythonToStubConverter.convert(PyContent, ModuleName) - - # 添加宏守卫(如果需要) - if self.config.GenerateGuards: - guard_name = self._GenerateGuardName(InputFile) - guard_comment = f"\n# Guard: {guard_name}\n" - content = content + guard_comment - - return content - - def run(self) -> bool: - """运行生成器""" - self.logger.info("=" * 60) - self.logger.info("StubGen - C/H/Py to Python Stub Generator") - self.logger.info("=" * 60) - - # 查找输入文件 - InputFiles = self.FindInputFiles() - - if not InputFiles: - self.logger.warning("No input files found!") - return False - - self.logger.info(f"Found {len(InputFiles)} input file(s)") - for FilePath, RelPath in InputFiles: - self.logger.debug(f" - {RelPath}") - - # 处理每个文件 - SuccessCount = 0 - for FilePath, RelPath in InputFiles: - if self.GenerateStub(FilePath, RelPath): - SuccessCount += 1 - - # 输出统计信息 - self.logger.info("=" * 60) - self.logger.info(f"Summary: {SuccessCount}/{len(InputFiles)} files generated successfully") - - if self.FailedFiles: - self.logger.warning(f"Failed files ({len(self.FailedFiles)}):") - for f in self.FailedFiles: - self.logger.warning(f" - {f}") - - return SuccessCount == len(InputFiles) - - -def main(): - parser = argparse.ArgumentParser( - description='StubGen - Generate Python stub files from C/H/Py sources', - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=''' -Examples: - # 使用配置文件 - %(prog)s -c config.json - - # 处理单个文件 - %(prog)s -i input.h -o output.py - - # 批量处理目录(保持目录结构) - %(prog)s -d ./kernel -o ./kernel/include - - # 干运行(不实际生成文件) - %(prog)s -d ./kernel --dry-run - - # 不生成宏守卫 - %(prog)s -d ./kernel --no-guards - ''' - ) - - # 输入选项 - InputGroup = parser.add_mutually_exclusive_group(required=True) - InputGroup.add_argument('-c', '--config', help='Configuration file (JSON)') - InputGroup.add_argument('-i', '--input', help='Input file') - InputGroup.add_argument('-d', '--directory', help='Input directory') - - # 输出选项 - parser.add_argument('-o', '--output', help='Output directory') - - # 其他选项 - parser.add_argument('--include', action='append', - help='Include patterns (default: *.h, *.c, *.py)') - parser.add_argument('--exclude', action='append', - help='Exclude patterns') - parser.add_argument('--no-guards', action='store_true', - help='Do not generate guard macros') - parser.add_argument('--no-structure', action='store_true', - help='Do not preserve directory structure') - parser.add_argument('-v', '--verbose', action='store_true', - help='Verbose output') - parser.add_argument('--dry-run', action='store_true', - help='Dry run (do not create files)') - - args = parser.parse_args() - - # 加载配置 - if args.config: - if not os.path.exists(args.config): - print(f"Error: Config file not found: {args.config}") - sys.exit(1) - config = StubGenConfig.from_file(args.config) - else: - config = StubGenConfig() - config.IncludePatterns = args.include or ['*.h', '*.c', '*.py'] - config.ExcludePatterns = args.exclude or [] - config.GenerateGuards = not args.no_guards - config.PreserveStructure = not args.no_structure - config.verbose = args.verbose - config.DryRun = args.dry_run - - if args.input: - config.InputFiles = [args.input] - if args.output: - config.OutputDir = os.path.dirname(args.output) or '.' - elif args.directory: - config.InputDir = args.directory - if args.output: - config.OutputDir = args.output - - # 创建生成器并运行 - generator = StubGen(config) - - # 如果指定了单个输出文件,直接处理 - if args.input and args.output and not os.path.isdir(args.output): - RelPath = os.path.relpath(args.input, config.InputDir or '.') - success = generator.GenerateStub(args.input, RelPath) - else: - success = generator.run() - - sys.exit(0 if success else 1) - - -if __name__ == '__main__': - main() +#!/usr/bin/env python3 +"""StubGen - C/H/Py 文件到 Python 存根文件生成器(工程化版本)""" +import sys +import os +sys.path.insert(0, os.path.dirname(__file__)) + +from lib.StubGen import StubGenConfig, PythonToStubConverter, StubGen, main + +__all__ = ['StubGenConfig', 'PythonToStubConverter', 'StubGen', 'main'] + +if __name__ == '__main__': + main() diff --git a/TODO b/TODO index 0f257e9..715c0f9 100644 --- a/TODO +++ b/TODO @@ -3,4 +3,4 @@ main 收集 元类型 @p.set - +函数的描述符用装饰器而不是返回值 diff --git a/Test/BuiltinDecoratorTest/App/main.py b/Test/BuiltinDecoratorTest/App/main.py index be3bbb9..17d9da4 100644 --- a/Test/BuiltinDecoratorTest/App/main.py +++ b/Test/BuiltinDecoratorTest/App/main.py @@ -1,6 +1,7 @@ import t from stdint import * from stdio import printf +from stdlib import malloc # ============================================================ # 测试计数器 @@ -25,6 +26,9 @@ class Rect: width: t.CInt height: t.CInt + def __new__(self, w: t.CInt, h: t.CInt) -> 'Rect' | t.CPtr: + return t.CPtr(malloc(Rect.__sizeof__())) + def __init__(self, w: t.CInt, h: t.CInt): self.width = w self.height = h @@ -40,9 +44,9 @@ class Rect: def test_property_getter(): printf("\n+-- @property getter --+\n") - r: Rect = Rect(3, 4) - check("area == 12", r.area == 12) - check("not square", not r.is_square) + r1: Rect = Rect(3, 4) + check("area == 12", r1.area == 12) + check("not square", not r1.is_square) r2: Rect = Rect(5, 5) check("square area == 25", r2.area == 25) check("is_square", r2.is_square) @@ -55,8 +59,11 @@ def test_property_getter(): class Temperature: _celsius: t.CDouble - def __init__(self, c: t.CDouble): - self._celsius = c + def __new__(self, celsius_val: t.CDouble) -> 'Temperature' | t.CPtr: + return t.CPtr(malloc(Temperature.__sizeof__())) + + def __init__(self, celsius_val: t.CDouble): + self._celsius = celsius_val @property def celsius(self) -> t.CDouble: @@ -73,11 +80,11 @@ class Temperature: def test_property_setter(): printf("\n+-- @property.setter --+\n") - t1: Temperature = Temperature(0.0) - check("0C == 32F", t1.fahrenheit > 31.9 and t1.fahrenheit < 32.1) - t1.celsius = 100.0 - check("100C == 212F", t1.fahrenheit > 211.9 and t1.fahrenheit < 212.1) - check("celsius == 100", t1.celsius > 99.9 and t1.celsius < 100.1) + tmp1: Temperature = Temperature(0.0) + check("0C == 32F", tmp1.fahrenheit > 31.9 and tmp1.fahrenheit < 32.1) + tmp1.celsius = 100.0 + check("100C == 212F", tmp1.fahrenheit > 211.9 and tmp1.fahrenheit < 212.1) + check("celsius == 100", tmp1.celsius > 99.9 and tmp1.celsius < 100.1) printf("+--------------------------------------------+\n") @@ -87,6 +94,9 @@ def test_property_setter(): class Counter: _count: t.CInt + def __new__(self) -> 'Counter' | t.CPtr: + return t.CPtr(malloc(Counter.__sizeof__())) + def __init__(self): self._count = 0 @@ -101,10 +111,10 @@ class Counter: def test_property_getter_redef(): printf("\n+-- @property.getter redef --+\n") - c: Counter = Counter() - check("init == 0", c.value == 0) - c.value = 42 - check("set == 42", c.value == 42) + cnt: Counter = Counter() + check("init == 0", cnt.value == 0) + cnt.value = 42 + check("set == 42", cnt.value == 42) printf("+--------------------------------------------+\n") @@ -115,6 +125,9 @@ class Config: _value: t.CInt _deleted: t.CInt + def __new__(self, v: t.CInt) -> 'Config' | t.CPtr: + return t.CPtr(malloc(Config.__sizeof__())) + def __init__(self, v: t.CInt): self._value = v self._deleted = 0 @@ -165,10 +178,6 @@ def test_staticmethod(): # 通过类名调用 check("MathUtils.add(3,4)==7", MathUtils.add(3, 4) == 7) check("MathUtils.max(5,10)==10", MathUtils.max_val(5, 10) == 10) - # 通过实例调用 - m: MathUtils = MathUtils() - check("instance.add(1,2)==3", m.add(1, 2) == 3) - check("instance.max(8,3)==8", m.max_val(8, 3) == 8) printf("+--------------------------------------------+\n") @@ -179,6 +188,9 @@ class Point: x: t.CDouble y: t.CDouble + def __new__(self, x: t.CDouble, y: t.CDouble) -> 'Point' | t.CPtr: + return t.CPtr(malloc(Point.__sizeof__())) + def __init__(self, x: t.CDouble, y: t.CDouble): self.x = x self.y = y @@ -216,6 +228,9 @@ def test_classmethod(): class Circle: _radius: t.CDouble + def __new__(self, r: t.CDouble) -> 'Circle' | t.CPtr: + return t.CPtr(malloc(Circle.__sizeof__())) + def __init__(self, r: t.CDouble): self._radius = r @@ -242,14 +257,18 @@ class Circle: def test_combined(): printf("\n+-- Combined @property + @staticmethod + @classmethod --+\n") - c: Circle = Circle.unit() - check("unit radius ~= 1", c.radius > 0.99 and c.radius < 1.01) + # 先测试直接构造 + cr0: Circle = Circle(1.0) + check("direct radius ~= 1", cr0.radius > 0.99 and cr0.radius < 1.01) + check("direct area ~= pi", cr0.area > 3.14 and cr0.area < 3.15) + cr0.radius = 2.0 + check("direct radius 2.0", cr0.radius > 1.99 and cr0.radius < 2.01) + check("direct area ~= 4pi", cr0.area > 12.56 and cr0.area < 12.58) + # 测试 classmethod + cr1: Circle = Circle.unit() + check("unit radius ~= 1", cr1.radius > 0.99 and cr1.radius < 1.01) check("is_unit(1.0)", Circle.is_unit(1.0)) check("not is_unit(2.0)", not Circle.is_unit(2.0)) - check("unit area ~= pi", c.area > 3.14 and c.area < 3.15) - c.radius = 2.0 - check("radius 2.0", c.radius > 1.99 and c.radius < 2.01) - check("area ~= 4pi", c.area > 12.56 and c.area < 12.58) printf("+--------------------------------------------+\n") diff --git a/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json b/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json new file mode 100644 index 0000000..b9a8517 --- /dev/null +++ b/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/BuiltinDecoratorTest/temp/6c2029b306556c00.pyi b/Test/BuiltinDecoratorTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/BuiltinDecoratorTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/BuiltinDecoratorTest/temp/_sha1_map.txt b/Test/BuiltinDecoratorTest/temp/_sha1_map.txt index 6a4510e..5f7f065 100644 --- a/Test/BuiltinDecoratorTest/temp/_sha1_map.txt +++ b/Test/BuiltinDecoratorTest/temp/_sha1_map.txt @@ -1,3 +1,4 @@ 56cdd754a8a09347:includes/stdint.py +6c2029b306556c00:includes/stdlib.py 73edbcf76e32d00b:includes/stdio.py -7d5b7ce7c134ada7:main.py +b6069b01d8c9cc04:main.py diff --git a/Test/BuiltinDecoratorTest/temp/7d5b7ce7c134ada7.pyi b/Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi similarity index 82% rename from Test/BuiltinDecoratorTest/temp/7d5b7ce7c134ada7.pyi rename to Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi index 615ee86..be4ff19 100644 --- a/Test/BuiltinDecoratorTest/temp/7d5b7ce7c134ada7.pyi +++ b/Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi @@ -9,6 +9,7 @@ import c import t from stdint import * from stdio import printf +from stdlib import malloc _pass_count: t.CExtern | t.CInt _fail_count: t.CExtern | t.CInt @@ -19,6 +20,7 @@ def check(name: t.CChar | t.CPtr, condition: bool) -> t.CInt: pass class Rect: width: t.CInt height: t.CInt + def __new__(self: Rect, w: t.CInt, h: t.CInt) -> 'Rect' | t.CPtr: pass def __init__(self: Rect, w: t.CInt, h: t.CInt) -> t.CInt: pass @property def area(self: Rect) -> t.CInt: pass @@ -30,7 +32,8 @@ def test_property_getter() -> t.CInt: pass class Temperature: _celsius: t.CDouble - def __init__(self: Temperature, c: t.CDouble) -> t.CInt: pass + def __new__(self: Temperature, celsius_val: t.CDouble) -> 'Temperature' | t.CPtr: pass + def __init__(self: Temperature, celsius_val: t.CDouble) -> t.CInt: pass @property def celsius(self: Temperature) -> t.CDouble: pass @celsius.setter @@ -43,6 +46,7 @@ def test_property_setter() -> t.CInt: pass class Counter: _count: t.CInt + def __new__(self: Counter) -> 'Counter' | t.CPtr: pass def __init__(self: Counter) -> t.CInt: pass @property def value(self: Counter) -> t.CInt: pass @@ -55,6 +59,7 @@ def test_property_getter_redef() -> t.CInt: pass class Config: _value: t.CInt _deleted: t.CInt + def __new__(self: Config, v: t.CInt) -> 'Config' | t.CPtr: pass def __init__(self: Config, v: t.CInt) -> t.CInt: pass @property def value(self: Config) -> t.CInt: pass @@ -79,6 +84,7 @@ def test_staticmethod() -> t.CInt: pass class Point: x: t.CDouble y: t.CDouble + def __new__(self: Point, x: t.CDouble, y: t.CDouble) -> 'Point' | t.CPtr: pass def __init__(self: Point, x: t.CDouble, y: t.CDouble) -> t.CInt: pass @classmethod def origin(cls: Point) -> Point: pass @@ -91,6 +97,7 @@ def test_classmethod() -> t.CInt: pass class Circle: _radius: t.CDouble + def __new__(self: Circle, r: t.CDouble) -> 'Circle' | t.CPtr: pass def __init__(self: Circle, r: t.CDouble) -> t.CInt: pass @property def radius(self: Circle) -> t.CDouble: pass diff --git a/Test/CPythonTest/App/cpython.py b/Test/CPythonTest/App/cpython.py index 825ee53..f9fb785 100644 --- a/Test/CPythonTest/App/cpython.py +++ b/Test/CPythonTest/App/cpython.py @@ -1,25 +1,777 @@ import t, c +# ============================================================ +# PyObject — 所有 Python 对象的基类 +# ============================================================ class PyObject: ob_refcnt: t.CLong ob_type: t.CPtr -def Py_Initialize() -> t.CVoid | t.CExtern: - pass +# ============================================================ +# 引用计数 +# ============================================================ +def Py_INCREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def Py_DECREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def Py_XINCREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def Py_XDECREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def Py_DecRef(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass -def PyLong_FromLong(value: t.CLong) -> PyObject | t.CPtr | t.CExtern: - pass -def PyObject_Str(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.CExtern: - pass +# ============================================================ +# 解释器初始化/终止 +# ============================================================ +def Py_Initialize() -> t.CVoid | t.State: pass +def Py_Finalize() -> t.CVoid | t.State: pass +def Py_InitializeEx(initsigs: t.CInt) -> t.CVoid | t.State: pass +def Py_FinalizeEx() -> t.CInt | t.State: pass +def Py_IsInitialized() -> t.CInt | t.State: pass -def PyUnicode_AsUTF8(unicode_obj: PyObject | t.CPtr) -> str | t.CExtern: - pass -def Py_DecRef(obj: PyObject | t.CPtr) -> t.CVoid | t.CExtern: - pass +# ============================================================ +# PyConfig +# ============================================================ +class PySTATUS: + func: t.CConst | str + err_msg: t.CConst | str + exitcode: t.CInt -def Py_Finalize() -> t.CVoid | t.CExtern: - pass +class PyPreConfig: + _config_version: t.CInt + _config_init: t.CInt + parse_argv: t.CInt + isolated: t.CInt + use_environment: t.CInt + utf8_mode: t.CInt + coerce_c_locale: t.CInt + C_locale_warnings: t.CInt + allocator: t.CInt + dev_mode: t.CInt + +class PyWideStringList: + length: t.CSizeT + items: t.CPtr + +class PyConfig: + _config_version: t.CInt + _config_init: t.CInt + isolated: t.CInt + use_environment: t.CInt + dev_mode: t.CInt + install_signal_handlers: t.CInt + use_hash_seed: t.CInt + hash_seed: t.CUnsignedLong + faulthandler: t.CInt + tracemalloc: t.CInt + import_time: t.CInt + show_ref_count: t.CInt + dump_refs: t.CInt + dump_refs_file: t.CConst | str + malloc_stats: t.CInt + filesystem_errors: t.CInt + pycache_prefix: t.CConst | str + parse_argv: t.CInt + argv: PyWideStringList + program_name: t.CConst | str + xoptions: PyWideStringList + warnoptions: PyWideStringList + site_import: t.CInt + bytes_warning: t.CInt + warn_default_encoding: t.CInt + inspect: t.CInt + interactive: t.CInt + optimization_level: t.CInt + parser_debug: t.CInt + verbose: t.CInt + quiet: t.CInt + home: t.CConst | str + pythonpath_env: t.CConst | str + module_search_paths: PyWideStringList + module_search_paths_set: t.CInt + executable: t.CConst | str + base_executable: t.CConst | str + prefix: t.CConst | str + base_prefix: t.CConst | str + exec_prefix: t.CConst | str + base_exec_prefix: t.CConst | str + platlibdir: t.CConst | str + stdio_filename: t.CConst | str + +def PyConfig_InitPythonConfig(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass +def PyConfig_InitIsolatedConfig(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass +def PyConfig_Clear(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass +def PyConfig_Read(config: PyConfig | t.CPtr) -> PySTATUS | t.State: pass +def Py_InitializeFromConfig(config: PyConfig | t.CPtr) -> PySTATUS | t.State: pass +def Py_DecodeLocale(s: t.CConst | str) -> str | t.State: pass +def PyStatus_Exception(status: PySTATUS) -> t.CInt | t.State: pass + + +# ============================================================ +# 整数操作 (PyLong) +# ============================================================ +def PyLong_FromLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromUnsignedLong(v: t.CUnsignedLong) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromLongLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromUnsignedLongLong(v: t.CUnsignedLong) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromSsize_t(v: t.CPtrDiffT) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromSize_t(v: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyLong_FromDouble(v: t.CDouble) -> PyObject | t.CPtr | t.State: pass +def PyLong_AsLong(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass +def PyLong_AsUnsignedLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong | t.State: pass +def PyLong_AsLongLong(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass +def PyLong_AsUnsignedLongLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong | t.State: pass +def PyLong_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble | t.State: pass +def PyLong_AsSsize_t(obj: PyObject | t.CPtr) -> t.CPtrDiffT | t.State: pass +def PyLong_AsSize_t(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + + +# ============================================================ +# 浮点数操作 (PyFloat) +# ============================================================ +def PyFloat_FromDouble(v: t.CDouble) -> PyObject | t.CPtr | t.State: pass +def PyFloat_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble | t.State: pass +def PyFloat_FromString(s: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 字符串操作 (PyUnicode / PyBytes) +# ============================================================ +def PyUnicode_FromString(u: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyUnicode_FromStringAndSize(u: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyUnicode_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyUnicode_AsUTF8(obj: PyObject | t.CPtr) -> str | t.State: pass +def PyUnicode_AsUTF8AndSize(obj: PyObject | t.CPtr, size: t.CPtrDiffT | t.CPtr) -> str | t.State: pass +def PyUnicode_AsWideChar(obj: PyObject | t.CPtr, wbuf: t.CPtr, bufsize: t.CSizeT) -> t.CSizeT | t.State: pass +def PyUnicode_GetLength(obj: PyObject | t.CPtr) -> t.CPtrDiffT | t.State: pass +def PyUnicode_ReadChar(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CUInt32T | t.State: pass +def PyUnicode_WriteChar(obj: PyObject | t.CPtr, idx: t.CSizeT, ch: t.CUInt32T) -> t.CInt | t.State: pass +def PyUnicode_Compare(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyUnicode_Concat(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyUnicode_Contains(container: PyObject | t.CPtr, element: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyUnicode_Format(fmt: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyUnicode_InternInPlace(s: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass +def PyUnicode_InternFromString(u: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyBytes_FromString(v: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyBytes_FromStringAndSize(v: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyBytes_AsString(obj: PyObject | t.CPtr) -> str | t.State: pass +def PyBytes_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyBytes_FromObject(o: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyBytes_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 布尔 / None +# ============================================================ +def PyBool_FromLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass + +Py_True: PyObject | t.CPtr | t.State +Py_False: PyObject | t.CPtr | t.State +Py_None: PyObject | t.CPtr | t.State + + +# ============================================================ +# 列表操作 (PyList) +# ============================================================ +def PyList_New(len: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyList_Size(lst: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyList_GetItem(lst: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyList_SetItem(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_Insert(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_Append(lst: PyObject | t.CPtr, item: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_GetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyList_SetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT, items: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_Sort(lst: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_Reverse(lst: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_AsTuple(lst: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 元组操作 (PyTuple) +# ============================================================ +def PyTuple_New(len: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyTuple_Size(tup: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyTuple_GetItem(tup: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyTuple_SetItem(tup: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyTuple_GetSlice(tup: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PyTuple_Pack(n: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 字典操作 (PyDict) +# ============================================================ +def PyDict_New() -> PyObject | t.CPtr | t.State: pass +def PyDict_GetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyDict_GetItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyDict_SetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyDict_SetItemString(d: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyDict_DelItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyDict_DelItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt | t.State: pass +def PyDict_Size(d: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyDict_Keys(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyDict_Values(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyDict_Items(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyDict_Copy(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyDict_Clear(d: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PyDict_Contains(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyDict_Next(d: PyObject | t.CPtr, pos: t.CPtrDiffT | t.CPtr, key: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr) -> t.CInt | t.State: pass +def PyDict_Merge(d: PyObject | t.CPtr, other: PyObject | t.CPtr, override: t.CInt) -> t.CInt | t.State: pass +def PyDict_Update(d: PyObject | t.CPtr, other: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 对象通用操作 +# ============================================================ +def PyObject_Str(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_Repr(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_Type(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_IsInstance(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_IsSubclass(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_HasAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_HasAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass +def PyObject_GetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_GetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyObject_SetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_SetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_DelAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_DelAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass +def PyObject_Call(callable: PyObject | t.CPtr, args: PyObject | t.CPtr, kwargs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_CallNoArgs(callable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_CallOneArg(callable: PyObject | t.CPtr, arg: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_IsTrue(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_Not(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_RichCompare(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> PyObject | t.CPtr | t.State: pass +def PyObject_RichCompareBool(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> t.CInt | t.State: pass +def PyObject_Hash(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass +def PyObject_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyObject_GetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_SetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_DelItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyObject_Dir(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_GetIter(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyIter_Next(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 比较常量 +# ============================================================ +Py_LT: t.CInt | t.State +Py_LE: t.CInt | t.State +Py_EQ: t.CInt | t.State +Py_NE: t.CInt | t.State +Py_GT: t.CInt | t.State +Py_GE: t.CInt | t.State + + +# ============================================================ +# 模块操作 +# ============================================================ +def PyImport_ImportModule(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyImport_Import(name: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyImport_ImportModuleLevelObject(name: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr, level: t.CInt) -> PyObject | t.CPtr | t.State: pass +def PyImport_ReloadModule(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyImport_AddModule(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyImport_GetModuleDict() -> PyObject | t.CPtr | t.State: pass +def PyImport_ImportModuleEx(name: t.CConst | str, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 模块创建 +# ============================================================ +class PyMethodDef: + ml_name: t.CConst | str + ml_meth: t.CPtr + ml_flags: t.CInt + ml_doc: t.CConst | str + +class PyModuleDef_Base: + ob_base: PyObject + m_init: t.CPtr + m_index: t.CSizeT + m_copy: PyObject | t.CPtr + +class PyModuleDef: + m_base: PyModuleDef_Base + m_name: t.CConst | str + m_doc: t.CConst | str + m_size: t.CPtrDiffT + m_methods: PyMethodDef | t.CPtr + m_slots: t.CPtr + m_traverse: t.CPtr + m_clear: t.CPtr + m_free: t.CPtr + +def PyModule_Create(mod: PyModuleDef | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyModule_Create2(mod: PyModuleDef | t.CPtr, ver: t.CInt) -> PyObject | t.CPtr | t.State: pass +def PyModule_GetName(mod: PyObject | t.CPtr) -> str | t.State: pass +def PyModule_GetDict(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyModule_GetFilenameObject(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyModule_AddObject(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyModule_AddObjectRef(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyModule_AddIntConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CLong) -> t.CInt | t.State: pass +def PyModule_AddStringConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CConst | str) -> t.CInt | t.State: pass + + +# ============================================================ +# GIL 管理 +# ============================================================ +def PyGILState_Ensure() -> t.CInt | t.State: pass +def PyGILState_Release(state: t.CInt) -> t.CVoid | t.State: pass +def PyEval_SaveThread() -> t.CPtr | t.State: pass +def PyEval_RestoreThread(tstate: t.CPtr) -> t.CVoid | t.State: pass +def PyEval_AcquireThread(tstate: t.CPtr) -> t.CVoid | t.State: pass +def PyEval_ReleaseThread(tstate: t.CPtr) -> t.CVoid | t.State: pass +def PyEval_AcquireLock() -> t.CVoid | t.State: pass +def PyEval_ReleaseLock() -> t.CVoid | t.State: pass +def PyEval_ThreadsInitialized() -> t.CInt | t.State: pass +def PyEval_InitThreads() -> t.CVoid | t.State: pass + + +# ============================================================ +# 错误处理 +# ============================================================ +def PyErr_Occurred() -> PyObject | t.CPtr | t.State: pass +def PyErr_Clear() -> t.CVoid | t.State: pass +def PyErr_Fetch(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass +def PyErr_Restore(tp: PyObject | t.CPtr, val: PyObject | t.CPtr, tb: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PyErr_NormalizeException(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass +def PyErr_SetString(tp: PyObject | t.CPtr, msg: t.CConst | str) -> t.CVoid | t.State: pass +def PyErr_SetObject(tp: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PyErr_BadArgument() -> t.CPtr | t.State: pass +def PyErr_NoMemory() -> t.CPtr | t.State: pass +def PyErr_Print() -> t.CVoid | t.State: pass +def PyErr_ExceptionMatches(exc: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyErr_GivenExceptionMatches(given: PyObject | t.CPtr, exc: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 内置异常类型 +# ============================================================ +PyExc_BaseException: PyObject | t.CPtr | t.State +PyExc_Exception: PyObject | t.CPtr | t.State +PyExc_TypeError: PyObject | t.CPtr | t.State +PyExc_ValueError: PyObject | t.CPtr | t.State +PyExc_RuntimeError: PyObject | t.CPtr | t.State +PyExc_KeyError: PyObject | t.CPtr | t.State +PyExc_IndexError: PyObject | t.CPtr | t.State +PyExc_AttributeError: PyObject | t.CPtr | t.State +PyExc_ImportError: PyObject | t.CPtr | t.State +PyExc_OSError: PyObject | t.CPtr | t.State +PyExc_IOError: PyObject | t.CPtr | t.State +PyExc_ZeroDivisionError: PyObject | t.CPtr | t.State +PyExc_OverflowError: PyObject | t.CPtr | t.State +PyExc_MemoryError: PyObject | t.CPtr | t.State +PyExc_NameError: PyObject | t.CPtr | t.State +PyExc_StopIteration: PyObject | t.CPtr | t.State +PyExc_NotImplementedError: PyObject | t.CPtr | t.State +PyExc_SyntaxError: PyObject | t.CPtr | t.State +PyExc_FileNotFoundError: PyObject | t.CPtr | t.State +PyExc_PermissionError: PyObject | t.CPtr | t.State +PyExc_IsADirectoryError: PyObject | t.CPtr | t.State +PyExc_NotADirectoryError: PyObject | t.CPtr | t.State + + +# ============================================================ +# 内置函数 +# ============================================================ +def Py_BuildValue(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def Py_VaBuildValue(fmt: t.CConst | str, va: t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 类型检查 +# ============================================================ +def PyLong_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyFloat_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyUnicode_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyBytes_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyList_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyTuple_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyDict_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyBool_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyNone_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 内存管理 +# ============================================================ +def PyMem_Malloc(size: t.CSizeT) -> t.CPtr | t.State: pass +def PyMem_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr | t.State: pass +def PyMem_Free(ptr: t.CPtr) -> t.CVoid | t.State: pass +def PyMem_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr | t.State: pass +def PyObject_Malloc(size: t.CSizeT) -> t.CPtr | t.State: pass +def PyObject_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr | t.State: pass +def PyObject_Free(ptr: t.CPtr) -> t.CVoid | t.State: pass +def PyObject_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr | t.State: pass +def PyObject_Init(obj: PyObject | t.CPtr, tp: t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyObject_InitVar(obj: PyObject | t.CPtr, tp: t.CPtr, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 文件操作 +# ============================================================ +def PyFile_FromString(filename: t.CConst | str, mode: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyFile_AsFile(file: PyObject | t.CPtr) -> t.CPtr | t.State: pass +def PyFile_WriteObject(obj: PyObject | t.CPtr, file: PyObject | t.CPtr, flags: t.CInt) -> t.CInt | t.State: pass +def PyFile_WriteString(s: t.CConst | str, file: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 编译/执行 +# ============================================================ +def Py_CompileString(s: t.CConst | str, filename: t.CConst | str, start: t.CInt) -> PyObject | t.CPtr | t.State: pass +def PyEval_EvalCode(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyEval_EvalCodeEx(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, args: PyObject | t.CPtr | t.CPtr, argc: t.CInt, kws: PyObject | t.CPtr | t.CPtr, kwc: t.CInt, defs: PyObject | t.CPtr | t.CPtr, defc: t.CInt, kwdefs: PyObject | t.CPtr, closure: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyEval_EvalFrame(frame: t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyEval_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyEval_CallFunction(callable: PyObject | t.CPtr, fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyEval_CallMethod(obj: PyObject | t.CPtr, method: t.CConst | str, fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# PyRun +# ============================================================ +def PyRun_SimpleString(cmd: t.CConst | str) -> t.CInt | t.State: pass +def PyRun_SimpleFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt | t.State: pass +def PyRun_AnyFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt | t.State: pass +def PyRun_String(s: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyRun_File(fp: t.CPtr, filename: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +Py_single_input: t.CInt | t.State +Py_file_input: t.CInt | t.State +Py_eval_input: t.CInt | t.State + + +# ============================================================ +# Capsule +# ============================================================ +def PyCapsule_New(ptr: t.CPtr, name: t.CConst | str, dtor: t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyCapsule_GetPointer(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CPtr | t.State: pass +def PyCapsule_GetName(cap: PyObject | t.CPtr) -> str | t.State: pass +def PyCapsule_IsValid(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass +def PyCapsule_SetPointer(cap: PyObject | t.CPtr, ptr: t.CPtr) -> t.CInt | t.State: pass +def PyCapsule_SetName(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass +def PyCapsule_SetDestructor(cap: PyObject | t.CPtr, dtor: t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 序列操作 +# ============================================================ +def PySequence_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySequence_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PySequence_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PySequence_Concat(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PySequence_Repeat(obj: PyObject | t.CPtr, count: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PySequence_GetItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PySequence_SetItem(obj: PyObject | t.CPtr, idx: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySequence_DelItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CInt | t.State: pass +def PySequence_GetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> PyObject | t.CPtr | t.State: pass +def PySequence_SetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySequence_DelSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> t.CInt | t.State: pass +def PySequence_Contains(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySequence_Index(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PySequence_Count(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PySequence_List(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PySequence_Tuple(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 映射操作 +# ============================================================ +def PyMapping_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyMapping_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyMapping_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PyMapping_HasKey(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyMapping_HasKeyString(obj: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt | t.State: pass +def PyMapping_GetItemString(obj: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PyMapping_SetItemString(obj: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyMapping_Keys(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyMapping_Values(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyMapping_Items(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +# ============================================================ +# 数字操作 +# ============================================================ +def PyNumber_Add(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Subtract(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Multiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_MatrixMultiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_FloorDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_TrueDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Modulo(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Power(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, o3: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Negative(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Positive(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Absolute(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Invert(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Lshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Rshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_And(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Xor(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Or(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Index(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Long(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Float(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyNumber_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 弱引用 +# ============================================================ +def PyWeakref_NewRef(obj: PyObject | t.CPtr, cb: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyWeakref_GetObject(ref: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyWeakref_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 属性描述符 +# ============================================================ +class PyGetSetDef: + name: t.CConst | str + get: t.CPtr + set: t.CPtr + doc: t.CConst | str + closure: t.CPtr + +class PyMemberDef: + name: t.CConst | str + type: t.CInt + offset: t.CPtrDiffT + flags: t.CInt + doc: t.CConst | str + + +# ============================================================ +# sys 模块 +# ============================================================ +def PySys_GetObject(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass +def PySys_SetObject(name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySys_ResetWarnOptions() -> t.CVoid | t.State: pass +def PySys_AddWarnOption(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PySYS_AddXOption(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PySys_WriteStdout(fmt: t.CConst | str) -> t.CVoid | t.State: pass +def PySys_WriteStderr(fmt: t.CConst | str) -> t.CVoid | t.State: pass +def PySys_FormatStdout(fmt: t.CConst | str) -> t.CVoid | t.State: pass +def PySys_FormatStderr(fmt: t.CConst | str) -> t.CVoid | t.State: pass + + +# ============================================================ +# 内存视图 +# ============================================================ +def PyMemoryView_FromObject(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyMemoryView_GetContiguous(obj: PyObject | t.CPtr, btype: t.CInt, order: t.CChar) -> PyObject | t.CPtr | t.State: pass +def PyMemoryView_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# set / frozenset +# ============================================================ +def PySet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PySet_Add(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySet_Discard(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySet_Contains(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PySet_Size(s: PyObject | t.CPtr) -> t.CSizeT | t.State: pass +def PySet_Clear(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass +def PySet_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass +def PyFrozenSet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PyFrozenSet_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# slice +# ============================================================ +def PySlice_New(start: PyObject | t.CPtr, stop: PyObject | t.CPtr, step: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass +def PySlice_GetIndicesEx(sl: PyObject | t.CPtr, length: t.CSizeT, start: t.CSizeT | t.CPtr, stop: t.CSizeT | t.CPtr, step: t.CSizeT | t.CPtr, slicelen: t.CSizeT | t.CPtr) -> t.CInt | t.State: pass +def PySlice_Unpack(sl: PyObject | t.CPtr, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT | t.CPtr) -> t.CVoid | t.State: pass +def PySlice_AdjustIndices(length: t.CSizeT, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT) -> t.CSizeT | t.State: pass +def PySlice_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 类型包装类 — 带运算符重载 +# ============================================================ + +# --- PyLongObj: Python 整数包装 --- +class PyLongObj: + ptr: PyObject | t.CPtr + + def __new__(self) -> 'PyLongObj' | t.CPtr: + return t.CPtr(malloc(PyLongObj.__sizeof__())) + + @staticmethod + def from_long(val: t.CLong) -> 'PyLongObj' | t.CPtr: + obj: PyLongObj | t.CPtr = PyLongObj() + obj.ptr = PyLong_FromLong(val) + return obj + + def __add__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: + res: PyLongObj | t.CPtr = PyLongObj() + res.ptr = PyNumber_Add(self.ptr, other.ptr) + return res + + def __sub__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: + res: PyLongObj | t.CPtr = PyLongObj() + res.ptr = PyNumber_Subtract(self.ptr, other.ptr) + return res + + def __mul__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: + res: PyLongObj | t.CPtr = PyLongObj() + res.ptr = PyNumber_Multiply(self.ptr, other.ptr) + return res + + def __neg__(self) -> 'PyLongObj' | t.CPtr: + res: PyLongObj | t.CPtr = PyLongObj() + res.ptr = PyNumber_Negative(self.ptr) + return res + + def to_long(self) -> t.CLong: + return PyLong_AsLong(self.ptr) + + def __str__(self) -> PyObject | t.CPtr: + return PyObject_Str(self.ptr) + + def dec_ref(self): + Py_DecRef(self.ptr) + + +# --- PyFloatObj: Python 浮点数包装 --- +class PyFloatObj: + ptr: PyObject | t.CPtr + + def __new__(self) -> 'PyFloatObj' | t.CPtr: + return t.CPtr(malloc(PyFloatObj.__sizeof__())) + + @staticmethod + def from_double(val: t.CDouble) -> 'PyFloatObj' | t.CPtr: + obj: PyFloatObj | t.CPtr = PyFloatObj() + obj.ptr = PyFloat_FromDouble(val) + return obj + + def __add__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: + res: PyFloatObj | t.CPtr = PyFloatObj() + res.ptr = PyNumber_Add(self.ptr, other.ptr) + return res + + def __sub__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: + res: PyFloatObj | t.CPtr = PyFloatObj() + res.ptr = PyNumber_Subtract(self.ptr, other.ptr) + return res + + def __mul__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: + res: PyFloatObj | t.CPtr = PyFloatObj() + res.ptr = PyNumber_Multiply(self.ptr, other.ptr) + return res + + def __truediv__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: + res: PyFloatObj | t.CPtr = PyFloatObj() + res.ptr = PyNumber_TrueDivide(self.ptr, other.ptr) + return res + + def __neg__(self) -> 'PyFloatObj' | t.CPtr: + res: PyFloatObj | t.CPtr = PyFloatObj() + res.ptr = PyNumber_Negative(self.ptr) + return res + + def to_double(self) -> t.CDouble: + return PyFloat_AsDouble(self.ptr) + + def __str__(self) -> PyObject | t.CPtr: + return PyObject_Str(self.ptr) + + def dec_ref(self): + Py_DecRef(self.ptr) + + +# --- PyUnicodeObj: Python 字符串包装 --- +class PyUnicodeObj: + ptr: PyObject | t.CPtr + + def __new__(self) -> 'PyUnicodeObj' | t.CPtr: + return t.CPtr(malloc(PyUnicodeObj.__sizeof__())) + + @staticmethod + def from_string(s: t.CChar | t.CPtr) -> 'PyUnicodeObj' | t.CPtr: + obj: PyUnicodeObj | t.CPtr = PyUnicodeObj() + obj.ptr = PyUnicode_FromString(s) + return obj + + def __add__(self, other: PyUnicodeObj | t.CPtr) -> 'PyUnicodeObj' | t.CPtr: + res: PyUnicodeObj | t.CPtr = PyUnicodeObj() + res.ptr = PyUnicode_Concat(self.ptr, other.ptr) + return res + + def __len__(self) -> t.CPtrDiffT: + return PyUnicode_GetLength(self.ptr) + + def as_utf8(self) -> t.CChar | t.CPtr: + return PyUnicode_AsUTF8(self.ptr) + + def __str__(self) -> PyObject | t.CPtr: + return self.ptr + + def dec_ref(self): + Py_DecRef(self.ptr) + + +# --- PyListObj: Python 列表包装 --- +class PyListObj: + ptr: PyObject | t.CPtr + + def __new__(self) -> 'PyListObj' | t.CPtr: + return t.CPtr(malloc(PyListObj.__sizeof__())) + + @staticmethod + def new() -> 'PyListObj' | t.CPtr: + obj: PyListObj | t.CPtr = PyListObj() + obj.ptr = PyList_New(0) + return obj + + def __getitem__(self, idx: t.CSizeT) -> PyObject | t.CPtr: + return PyList_GetItem(self.ptr, idx) + + def __setitem__(self, idx: t.CSizeT, val: PyObject | t.CPtr): + PyList_SetItem(self.ptr, idx, val) + + def __len__(self) -> t.CSizeT: + return PyList_Size(self.ptr) + + def append(self, item: PyObject | t.CPtr) -> t.CInt: + return PyList_Append(self.ptr, item) + + def dec_ref(self): + Py_DecRef(self.ptr) + + +# --- PyDictObj: Python 字典包装 --- +class PyDictObj: + ptr: PyObject | t.CPtr + + def __new__(self) -> 'PyDictObj' | t.CPtr: + return t.CPtr(malloc(PyDictObj.__sizeof__())) + + @staticmethod + def new() -> 'PyDictObj' | t.CPtr: + obj: PyDictObj | t.CPtr = PyDictObj() + obj.ptr = PyDict_New() + return obj + + def __getitem__(self, key: PyObject | t.CPtr) -> PyObject | t.CPtr: + return PyDict_GetItem(self.ptr, key) + + def __setitem__(self, key: PyObject | t.CPtr, val: PyObject | t.CPtr): + PyDict_SetItem(self.ptr, key, val) + + def __len__(self) -> t.CSizeT: + return PyDict_Size(self.ptr) + + def get_string(self, key: t.CChar | t.CPtr) -> PyObject | t.CPtr: + return PyDict_GetItemString(self.ptr, key) + + def set_string(self, key: t.CChar | t.CPtr, val: PyObject | t.CPtr): + PyDict_SetItemString(self.ptr, key, val) + + def dec_ref(self): + Py_DecRef(self.ptr) diff --git a/Test/CPythonTest/App/main.py b/Test/CPythonTest/App/main.py index f0aa5e7..8e66d08 100644 --- a/Test/CPythonTest/App/main.py +++ b/Test/CPythonTest/App/main.py @@ -1,28 +1,380 @@ import t, c -from t import CInt, CPtr, CChar, CLong -import viperlib +from t import CInt, CLong, CDouble, CPtr, CSizeT +from stdio import printf import cpython -def SetDllDirectoryA(lpPathName: str | CPtr) -> CInt | t.CExtern: - pass +_pass_count: CInt = 0 +_fail_count: CInt = 0 -def main() -> CInt | t.CExport: - SetDllDirectoryA("D:\\Python312") +def check(name: t.CChar | CPtr, condition: bool): + global _pass_count, _fail_count + if condition: + _pass_count += 1 + printf(" [PASS] %s\n", name) + else: + _fail_count += 1 + printf(" [FAIL] %s\n", name) + +def test_init_finalize(): + printf("\n+-- Py_Initialize / Py_Finalize --+\n") + cpython.Py_Initialize() + check("Py_Initialize succeeded", cpython.Py_IsInitialized() != 0) + cpython.Py_Finalize() + check("Py_Finalize succeeded", cpython.Py_IsInitialized() == 0) + printf("+--------------------------------------------+\n") + + +def test_long_operations(): + printf("\n+-- PyLong operations --+\n") cpython.Py_Initialize() - py_num: cpython.PyObject | t.CPtr = cpython.PyLong_FromLong(12345) + # 创建整数 + py_num: cpython.PyObject | CPtr = cpython.PyLong_FromLong(12345) + check("PyLong_FromLong != NULL", py_num != 0) - py_str: cpython.PyObject | t.CPtr = cpython.PyObject_Str(py_num) - c_str: str = cpython.PyUnicode_AsUTF8(py_str) - print(c_str) + # 整数转字符串 + py_str: cpython.PyObject | CPtr = cpython.PyObject_Str(py_num) + check("PyObject_Str != NULL", py_str != 0) + # 获取 C 字符串 + c_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_str) + check("PyUnicode_AsUTF8 != NULL", c_str != 0) + printf(" PyLong_FromLong(12345) -> str = %s\n", c_str) + + # 读取回来 + val: CLong = cpython.PyLong_AsLong(py_num) + check("PyLong_AsLong == 12345", val == 12345) + + # 负数 + py_neg: cpython.PyObject | CPtr = cpython.PyLong_FromLong(-999) + neg_val: CLong = cpython.PyLong_AsLong(py_neg) + check("PyLong_FromLong(-999) == -999", neg_val == -999) + + # 浮点数转整数 + py_dbl: cpython.PyObject | CPtr = cpython.PyFloat_FromDouble(3.14159) + check("PyFloat_FromDouble != NULL", py_dbl != 0) + dbl_val: CDouble = cpython.PyFloat_AsDouble(py_dbl) + check("PyFloat_AsDouble ~= 3.14", dbl_val > 3.14 and dbl_val < 3.15) + + # 清理 + cpython.Py_DecRef(py_dbl) + cpython.Py_DecRef(py_neg) cpython.Py_DecRef(py_str) cpython.Py_DecRef(py_num) cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_string_operations(): + printf("\n+-- PyUnicode operations --+\n") + cpython.Py_Initialize() + + # 从 C 字符串创建 + py_s1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Hello, Viper!") + check("PyUnicode_FromString != NULL", py_s1 != 0) + + # 获取 UTF8 + utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_s1) + check("AsUTF8 != NULL", utf8 != 0) + printf(" PyUnicode_FromString -> %s\n", utf8) + + # 字符串长度 + length: CLong = cpython.PyUnicode_GetLength(py_s1) + check("GetLength == 13", length == 13) + + # 字符串拼接 + py_s2: cpython.PyObject | CPtr = cpython.PyUnicode_FromString(" World") + py_concat: cpython.PyObject | CPtr = cpython.PyUnicode_Concat(py_s1, py_s2) + concat_utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_concat) + check("Concat != NULL", py_concat != 0) + printf(" Concat -> %s\n", concat_utf8) + + # 清理 + cpython.Py_DecRef(py_concat) + cpython.Py_DecRef(py_s2) + cpython.Py_DecRef(py_s1) + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_list_operations(): + printf("\n+-- PyList operations --+\n") + cpython.Py_Initialize() + + # 创建列表 + py_list: cpython.PyObject | CPtr = cpython.PyList_New(0) + check("PyList_New != NULL", py_list != 0) + + # Append 元素 + py_i1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(10) + py_i2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(20) + py_i3: cpython.PyObject | CPtr = cpython.PyLong_FromLong(30) + cpython.PyList_Append(py_list, py_i1) + cpython.PyList_Append(py_list, py_i2) + cpython.PyList_Append(py_list, py_i3) + + # 检查大小 + list_size: CSizeT = cpython.PyList_Size(py_list) + check("PyList_Size == 3", list_size == 3) + + # 获取元素 + item0: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 0) + val0: CLong = cpython.PyLong_AsLong(item0) + check("list[0] == 10", val0 == 10) + + item2: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 2) + val2: CLong = cpython.PyLong_AsLong(item2) + check("list[2] == 30", val2 == 30) + + # 清理 + cpython.Py_DecRef(py_i3) + cpython.Py_DecRef(py_i2) + cpython.Py_DecRef(py_i1) + cpython.Py_DecRef(py_list) + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_dict_operations(): + printf("\n+-- PyDict operations --+\n") + cpython.Py_Initialize() + + # 创建字典 + py_dict: cpython.PyObject | CPtr = cpython.PyDict_New() + check("PyDict_New != NULL", py_dict != 0) + + # 设置键值对 + py_key1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("name") + py_val1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Viper") + cpython.PyDict_SetItem(py_dict, py_key1, py_val1) + + py_key2: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("version") + py_val2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(1) + cpython.PyDict_SetItem(py_dict, py_key2, py_val2) + + # 检查大小 + dict_size: CSizeT = cpython.PyDict_Size(py_dict) + check("PyDict_Size == 2", dict_size == 2) + + # 获取值 + got_val: cpython.PyObject | CPtr = cpython.PyDict_GetItem(py_dict, py_key1) + check("GetItem(name) != NULL", got_val != 0) + got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_val) + check("name == Viper", got_str != 0) + printf(" dict['name'] = %s\n", got_str) + + # 使用 GetItemString + got_ver: cpython.PyObject | CPtr = cpython.PyDict_GetItemString(py_dict, "version") + check("GetItemString(version) != NULL", got_ver != 0) + ver_val: CLong = cpython.PyLong_AsLong(got_ver) + check("version == 1", ver_val == 1) + + # 清理 + cpython.Py_DecRef(py_val2) + cpython.Py_DecRef(py_key2) + cpython.Py_DecRef(py_val1) + cpython.Py_DecRef(py_key1) + cpython.Py_DecRef(py_dict) + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_pyrun_string(): + printf("\n+-- PyRun_SimpleString --+\n") + cpython.Py_Initialize() + + # 执行简单 Python 代码 + rc: CInt = cpython.PyRun_SimpleString("print('Hello from embedded Python!')") + check("PyRun_SimpleString == 0", rc == 0) + + # 执行赋值 + rc2: CInt = cpython.PyRun_SimpleString("x = 6 * 7") + check("PyRun_SimpleString(assign) == 0", rc2 == 0) + + # 读取结果 + rc3: CInt = cpython.PyRun_SimpleString("print(f'The answer is {x}')") + check("PyRun_SimpleString(print) == 0", rc3 == 0) + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_import_module(): + printf("\n+-- PyImport_ImportModule --+\n") + cpython.Py_Initialize() + + # 导入 math 模块 + math_mod: cpython.PyObject | CPtr = cpython.PyImport_ImportModule("math") + check("import math != NULL", math_mod != 0) + + if math_mod != 0: + # 获取 math.pi + pi_val: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "pi") + check("math.pi != NULL", pi_val != 0) + if pi_val != 0: + pi_dbl: CDouble = cpython.PyFloat_AsDouble(pi_val) + check("math.pi ~= 3.14", pi_dbl > 3.14 and pi_dbl < 3.15) + printf(" math.pi = %f\n", pi_dbl) + cpython.Py_DecRef(pi_val) + + # 获取 math.sqrt 函数 + sqrt_func: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "sqrt") + check("math.sqrt != NULL", sqrt_func != 0) + if sqrt_func != 0: + cpython.Py_DecRef(sqrt_func) + + cpython.Py_DecRef(math_mod) + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def test_operator_overload(): + printf("\n+-- Operator Overload (PyLongObj / PyFloatObj / PyUnicodeObj / PyListObj / PyDictObj) --+\n") + cpython.Py_Initialize() + + # --- PyLongObj: from_long, to_long, +, -, *, - (neg) --- + a: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(10) + b: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(3) + check("PyLongObj.from_long != NULL", a != 0 and b != 0) + + add_r: cpython.PyLongObj | CPtr = a + b + check("PyLongObj 10 + 3 == 13", add_r.to_long() == 13) + + sub_r: cpython.PyLongObj | CPtr = a - b + check("PyLongObj 10 - 3 == 7", sub_r.to_long() == 7) + + mul_r: cpython.PyLongObj | CPtr = a * b + check("PyLongObj 10 * 3 == 30", mul_r.to_long() == 30) + + neg_r: cpython.PyLongObj | CPtr = -b + check("PyLongObj -3 == -3", neg_r.to_long() == -3) + + mul_r.dec_ref() + sub_r.dec_ref() + add_r.dec_ref() + neg_r.dec_ref() + b.dec_ref() + a.dec_ref() + + # --- PyFloatObj: from_double, to_double, +, -, *, /, - (neg) --- + fa: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(10.0) + fb: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(4.0) + check("PyFloatObj.from_double != NULL", fa != 0 and fb != 0) + + fadd: cpython.PyFloatObj | CPtr = fa + fb + check("PyFloatObj 10.0 + 4.0 == 14.0", fadd.to_double() == 14.0) + + fsub: cpython.PyFloatObj | CPtr = fa - fb + check("PyFloatObj 10.0 - 4.0 == 6.0", fsub.to_double() == 6.0) + + fmul: cpython.PyFloatObj | CPtr = fa * fb + check("PyFloatObj 10.0 * 4.0 == 40.0", fmul.to_double() == 40.0) + + fdiv: cpython.PyFloatObj | CPtr = fa / fb + check("PyFloatObj 10.0 / 4.0 == 2.5", fdiv.to_double() == 2.5) + + fneg: cpython.PyFloatObj | CPtr = -fb + check("PyFloatObj -4.0 == -4.0", fneg.to_double() == -4.0) + + fadd.dec_ref() + fsub.dec_ref() + fmul.dec_ref() + fdiv.dec_ref() + fneg.dec_ref() + fb.dec_ref() + fa.dec_ref() + + # --- PyUnicodeObj: from_string, as_utf8, len, + (concat) --- + sa: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string("Hello") + sb: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string(" World") + check("PyUnicodeObj.from_string != NULL", sa != 0 and sb != 0) + + sc: cpython.PyUnicodeObj | CPtr = sa + sb + sc_utf8: t.CChar | CPtr = sc.as_utf8() + check("PyUnicodeObj concat != NULL", sc_utf8 != 0) + if sc_utf8 != 0: + printf(" PyUnicodeObj 'Hello' + ' World' = %s\n", sc_utf8) + + sa_len: t.CPtrDiffT = len(sa) + check("PyUnicodeObj len('Hello') == 5", sa_len == 5) + + sc.dec_ref() + sb.dec_ref() + sa.dec_ref() + + # --- PyListObj: new, append, len, [], []= --- + lst: cpython.PyListObj | CPtr = cpython.PyListObj.new() + check("PyListObj.new != NULL", lst != 0) + if lst != 0: + e1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(100) + e2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(200) + e3: cpython.PyObject | CPtr = cpython.PyLong_FromLong(300) + lst.append(e1) + lst.append(e2) + lst.append(e3) + check("PyListObj len == 3", len(lst) == 3) + + item0: cpython.PyObject | CPtr = lst[t.CSizeT(0)] + check("PyListObj lst[0] == 100", cpython.PyLong_AsLong(item0) == 100) + + # __setitem__ + e4: cpython.PyObject | CPtr = cpython.PyLong_FromLong(999) + lst[t.CSizeT(1)] = e4 + item1: cpython.PyObject | CPtr = lst[t.CSizeT(1)] + check("PyListObj lst[1] = 999", cpython.PyLong_AsLong(item1) == 999) + + cpython.Py_DecRef(e4) + cpython.Py_DecRef(e3) + cpython.Py_DecRef(e2) + cpython.Py_DecRef(e1) + lst.dec_ref() + + # --- PyDictObj: new, [], []=, len, set_string, get_string --- + dct: cpython.PyDictObj | CPtr = cpython.PyDictObj.new() + check("PyDictObj.new != NULL", dct != 0) + if dct != 0: + dk1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("lang") + dv1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Viper") + dct[dk1] = dv1 + check("PyDictObj len == 1", len(dct) == 1) + + got_lang: cpython.PyObject | CPtr = dct[dk1] + got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_lang) + check("PyDictObj dct['lang'] == Viper", got_str != 0) + if got_str != 0: + printf(" PyDictObj dct['lang'] = %s\n", got_str) + + # get_string / set_string + dct.set_string("ver", cpython.PyLong_FromLong(3)) + got_ver: cpython.PyObject | CPtr = dct.get_string("ver") + check("PyDictObj get_string('ver') == 3", got_ver != 0 and cpython.PyLong_AsLong(got_ver) == 3) + + cpython.Py_DecRef(dv1) + cpython.Py_DecRef(dk1) + dct.dec_ref() + + cpython.Py_Finalize() + printf("+--------------------------------------------+\n") + + +def main() -> CInt | t.CExport: + printf("=== CPython Integration Test ===\n") + + test_init_finalize() + test_long_operations() + test_string_operations() + test_list_operations() + test_dict_operations() + test_pyrun_string() + test_import_module() + test_operator_overload() + + printf("\n=== Results: %d passed, %d failed ===\n", _pass_count, _fail_count) return 0 - - - diff --git a/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json b/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json new file mode 100644 index 0000000..f813be8 --- /dev/null +++ b/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "cpython": "7c5d5ec59c5fb0a8"} \ No newline at end of file diff --git a/Test/CPythonTest/output/3e1c3f98e99cff7a.deps.json b/Test/CPythonTest/output/3e1c3f98e99cff7a.deps.json deleted file mode 100644 index a44986b..0000000 --- a/Test/CPythonTest/output/3e1c3f98e99cff7a.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"viperlib": "4d342c40331fc964", "stdint": "56cdd754a8a09347", "main": "6999814920e8b3d5", "stdarg": "81ac26077a460417", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/CPythonTest/output/4d342c40331fc964.deps.json b/Test/CPythonTest/output/4d342c40331fc964.deps.json deleted file mode 100644 index 235982b..0000000 --- a/Test/CPythonTest/output/4d342c40331fc964.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"cpython": "3e1c3f98e99cff7a", "stdarg": "81ac26077a460417", "main": "93131e2ff5450838", "viperio": "d771d4d68d9e75b3"} \ No newline at end of file diff --git a/Test/CPythonTest/output/6999814920e8b3d5.deps.json b/Test/CPythonTest/output/6999814920e8b3d5.deps.json deleted file mode 100644 index eb248b3..0000000 --- a/Test/CPythonTest/output/6999814920e8b3d5.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"cpython": "3e1c3f98e99cff7a", "viperlib": "4d342c40331fc964", "stdint": "56cdd754a8a09347", "stdarg": "81ac26077a460417", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json b/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json new file mode 100644 index 0000000..7d8bc7a --- /dev/null +++ b/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json @@ -0,0 +1 @@ +{"main": "0cd580d62a3de4f8", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/CPythonTest/output/CPythonTest.exe.tmp0 b/Test/CPythonTest/output/CPythonTest.exe.tmp0 deleted file mode 100644 index 4b787d6..0000000 Binary files a/Test/CPythonTest/output/CPythonTest.exe.tmp0 and /dev/null differ diff --git a/Test/CPythonTest/output/c9f4be41ca1cc2b4.deps.json b/Test/CPythonTest/output/c9f4be41ca1cc2b4.deps.json deleted file mode 100644 index 44c72d1..0000000 --- a/Test/CPythonTest/output/c9f4be41ca1cc2b4.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"cpython": "3e1c3f98e99cff7a", "viperlib": "4d342c40331fc964", "stdint": "56cdd754a8a09347", "main": "6999814920e8b3d5", "stdarg": "81ac26077a460417"} \ No newline at end of file diff --git a/Test/CPythonTest/project.json b/Test/CPythonTest/project.json index 72d58cd..4daa736 100644 --- a/Test/CPythonTest/project.json +++ b/Test/CPythonTest/project.json @@ -11,19 +11,25 @@ }, "linker": { "cmd": "clang++", - "flags": ["-L", "D:\\Python312", "-lmsvcrt", "-lucrt", "-lpthread", "D:\\Python312\\python312.dll"], + "flags": [ + "-L", "D:\\Python312\\libs", + "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", + "-lkernel32", "-luser32", + "-lpython312", + "-Wl,--allow-multiple-definition" + ], "output": "CPythonTest.exe" }, "includes": [ "./includes" ], "target": { - "triple": "x86_64-pc-windows-msvc", + "triple": "x86_64-pc-windows-gnu", "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" }, "options": { "slice_level": 3, "target": "llvm", - "strict_mode": true + "strict_mode": false } } diff --git a/Test/CPythonTest/temp/0cd580d62a3de4f8.pyi b/Test/CPythonTest/temp/0cd580d62a3de4f8.pyi new file mode 100644 index 0000000..60b905d --- /dev/null +++ b/Test/CPythonTest/temp/0cd580d62a3de4f8.pyi @@ -0,0 +1,33 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +import t, c +from t import CInt, CLong, CDouble, CPtr, CSizeT +from stdio import printf +import cpython + +_pass_count: t.CExtern | CInt +_fail_count: t.CExtern | CInt + +def check(name: t.CChar | CPtr, condition: bool) -> t.CInt: pass + +def test_init_finalize() -> t.CInt: pass + +def test_long_operations() -> t.CInt: pass + +def test_string_operations() -> t.CInt: pass + +def test_list_operations() -> t.CInt: pass + +def test_dict_operations() -> t.CInt: pass + +def test_pyrun_string() -> t.CInt: pass + +def test_import_module() -> t.CInt: pass + +def test_operator_overload() -> t.CInt: pass + +def main() -> CInt | t.CExport: pass diff --git a/Test/CPythonTest/temp/3e1c3f98e99cff7a.pyi b/Test/CPythonTest/temp/3e1c3f98e99cff7a.pyi deleted file mode 100644 index fd235ae..0000000 --- a/Test/CPythonTest/temp/3e1c3f98e99cff7a.pyi +++ /dev/null @@ -1,23 +0,0 @@ -""" -Auto-generated Python stub file from cpython.py -Module: cpython -""" - - -import t, c - -class PyObject: - ob_refcnt: t.CLong - ob_type: t.CPtr - -def Py_Initialize() -> t.CVoid | t.CExtern | t.State: pass - -def PyLong_FromLong(value: t.CLong) -> PyObject | t.CPtr | t.CExtern | t.State: pass - -def PyObject_Str(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.CExtern | t.State: pass - -def PyUnicode_AsUTF8(unicode_obj: PyObject | t.CPtr) -> str | t.CExtern | t.State: pass - -def Py_DecRef(obj: PyObject | t.CPtr) -> t.CVoid | t.CExtern | t.State: pass - -def Py_Finalize() -> t.CVoid | t.CExtern | t.State: pass diff --git a/Test/CPythonTest/temp/6999814920e8b3d5.pyi b/Test/CPythonTest/temp/6999814920e8b3d5.pyi deleted file mode 100644 index 1c3efa5..0000000 --- a/Test/CPythonTest/temp/6999814920e8b3d5.pyi +++ /dev/null @@ -1,14 +0,0 @@ -""" -Auto-generated Python stub file from main.py -Module: main -""" - - -import t, c -from t import CInt, CPtr, CChar, CLong -import viperlib -import cpython - -def SetDllDirectoryA(lpPathName: str | CPtr) -> CInt | t.CExtern | t.State: pass - -def main() -> CInt | t.CExport | t.State: pass diff --git a/Test/CPythonTest/temp/73edbcf76e32d00b.pyi b/Test/CPythonTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/CPythonTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/CPythonTest/temp/7c5d5ec59c5fb0a8.pyi b/Test/CPythonTest/temp/7c5d5ec59c5fb0a8.pyi new file mode 100644 index 0000000..3c94870 --- /dev/null +++ b/Test/CPythonTest/temp/7c5d5ec59c5fb0a8.pyi @@ -0,0 +1,765 @@ +""" +Auto-generated Python stub file from cpython.py +Module: cpython +""" + + +import t, c + +class PyObject: + ob_refcnt: t.CLong + ob_type: t.CPtr + +def Py_INCREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def Py_DECREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def Py_XINCREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def Py_XDECREF(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def Py_DecRef(op: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def Py_Initialize() -> t.CVoid | t.State: pass + +def Py_Finalize() -> t.CVoid | t.State: pass + +def Py_InitializeEx(initsigs: t.CInt) -> t.CVoid | t.State: pass + +def Py_FinalizeEx() -> t.CInt | t.State: pass + +def Py_IsInitialized() -> t.CInt | t.State: pass + + +class PySTATUS: + func: t.CConst | str + err_msg: t.CConst | str + exitcode: t.CInt +class PyPreConfig: + _config_version: t.CInt + _config_init: t.CInt + parse_argv: t.CInt + isolated: t.CInt + use_environment: t.CInt + utf8_mode: t.CInt + coerce_c_locale: t.CInt + C_locale_warnings: t.CInt + allocator: t.CInt + dev_mode: t.CInt +class PyWideStringList: + length: t.CSizeT + items: t.CPtr +class PyConfig: + _config_version: t.CInt + _config_init: t.CInt + isolated: t.CInt + use_environment: t.CInt + dev_mode: t.CInt + install_signal_handlers: t.CInt + use_hash_seed: t.CInt + hash_seed: t.CUnsignedLong + faulthandler: t.CInt + tracemalloc: t.CInt + import_time: t.CInt + show_ref_count: t.CInt + dump_refs: t.CInt + dump_refs_file: t.CConst | str + malloc_stats: t.CInt + filesystem_errors: t.CInt + pycache_prefix: t.CConst | str + parse_argv: t.CInt + argv: PyWideStringList + program_name: t.CConst | str + xoptions: PyWideStringList + warnoptions: PyWideStringList + site_import: t.CInt + bytes_warning: t.CInt + warn_default_encoding: t.CInt + inspect: t.CInt + interactive: t.CInt + optimization_level: t.CInt + parser_debug: t.CInt + verbose: t.CInt + quiet: t.CInt + home: t.CConst | str + pythonpath_env: t.CConst | str + module_search_paths: PyWideStringList + module_search_paths_set: t.CInt + executable: t.CConst | str + base_executable: t.CConst | str + prefix: t.CConst | str + base_prefix: t.CConst | str + exec_prefix: t.CConst | str + base_exec_prefix: t.CConst | str + platlibdir: t.CConst | str + stdio_filename: t.CConst | str + +def PyConfig_InitPythonConfig(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass + +def PyConfig_InitIsolatedConfig(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass + +def PyConfig_Clear(config: PyConfig | t.CPtr) -> t.CVoid | t.State: pass + +def PyConfig_Read(config: PyConfig | t.CPtr) -> PySTATUS | t.State: pass + +def Py_InitializeFromConfig(config: PyConfig | t.CPtr) -> PySTATUS | t.State: pass + +def Py_DecodeLocale(s: t.CConst | str) -> str | t.State: pass + +def PyStatus_Exception(status: PySTATUS) -> t.CInt | t.State: pass + +def PyLong_FromLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromUnsignedLong(v: t.CUnsignedLong) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromLongLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromUnsignedLongLong(v: t.CUnsignedLong) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromSsize_t(v: t.CPtrDiffT) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromSize_t(v: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyLong_FromDouble(v: t.CDouble) -> PyObject | t.CPtr | t.State: pass + +def PyLong_AsLong(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass + +def PyLong_AsUnsignedLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong | t.State: pass + +def PyLong_AsLongLong(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass + +def PyLong_AsUnsignedLongLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong | t.State: pass + +def PyLong_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble | t.State: pass + +def PyLong_AsSsize_t(obj: PyObject | t.CPtr) -> t.CPtrDiffT | t.State: pass + +def PyLong_AsSize_t(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyFloat_FromDouble(v: t.CDouble) -> PyObject | t.CPtr | t.State: pass + +def PyFloat_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble | t.State: pass + +def PyFloat_FromString(s: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_FromString(u: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_FromStringAndSize(u: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_AsUTF8(obj: PyObject | t.CPtr) -> str | t.State: pass + +def PyUnicode_AsUTF8AndSize(obj: PyObject | t.CPtr, size: t.CPtrDiffT | t.CPtr) -> str | t.State: pass + +def PyUnicode_AsWideChar(obj: PyObject | t.CPtr, wbuf: t.CPtr, bufsize: t.CSizeT) -> t.CSizeT | t.State: pass + +def PyUnicode_GetLength(obj: PyObject | t.CPtr) -> t.CPtrDiffT | t.State: pass + +def PyUnicode_ReadChar(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CUInt32T | t.State: pass + +def PyUnicode_WriteChar(obj: PyObject | t.CPtr, idx: t.CSizeT, ch: t.CUInt32T) -> t.CInt | t.State: pass + +def PyUnicode_Compare(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyUnicode_Concat(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_Contains(container: PyObject | t.CPtr, element: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyUnicode_Format(fmt: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyUnicode_InternInPlace(s: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass + +def PyUnicode_InternFromString(u: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyBytes_FromString(v: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyBytes_FromStringAndSize(v: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyBytes_AsString(obj: PyObject | t.CPtr) -> str | t.State: pass + +def PyBytes_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyBytes_FromObject(o: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyBytes_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyBool_FromLong(v: t.CLong) -> PyObject | t.CPtr | t.State: pass + + +Py_True: t.CExtern | PyObject | t.CPtr | t.State +Py_False: t.CExtern | PyObject | t.CPtr | t.State +Py_None: t.CExtern | PyObject | t.CPtr | t.State + +def PyList_New(len: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyList_Size(lst: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyList_GetItem(lst: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyList_SetItem(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_Insert(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_Append(lst: PyObject | t.CPtr, item: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_GetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyList_SetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT, items: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_Sort(lst: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_Reverse(lst: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_AsTuple(lst: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyTuple_New(len: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyTuple_Size(tup: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyTuple_GetItem(tup: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyTuple_SetItem(tup: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyTuple_GetSlice(tup: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyTuple_Pack(n: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyDict_New() -> PyObject | t.CPtr | t.State: pass + +def PyDict_GetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyDict_GetItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyDict_SetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_SetItemString(d: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_DelItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_DelItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt | t.State: pass + +def PyDict_Size(d: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyDict_Keys(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyDict_Values(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyDict_Items(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyDict_Copy(d: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyDict_Clear(d: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PyDict_Contains(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_Next(d: PyObject | t.CPtr, pos: t.CPtrDiffT | t.CPtr, key: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_Merge(d: PyObject | t.CPtr, other: PyObject | t.CPtr, override: t.CInt) -> t.CInt | t.State: pass + +def PyDict_Update(d: PyObject | t.CPtr, other: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_Str(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_Repr(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_Type(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_IsInstance(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_IsSubclass(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_HasAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_HasAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass + +def PyObject_GetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_GetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyObject_SetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_SetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_DelAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_DelAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass + +def PyObject_Call(callable: PyObject | t.CPtr, args: PyObject | t.CPtr, kwargs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_CallNoArgs(callable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_CallOneArg(callable: PyObject | t.CPtr, arg: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_IsTrue(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_Not(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_RichCompare(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> PyObject | t.CPtr | t.State: pass + +def PyObject_RichCompareBool(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> t.CInt | t.State: pass + +def PyObject_Hash(obj: PyObject | t.CPtr) -> t.CLong | t.State: pass + +def PyObject_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyObject_GetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_SetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_DelItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyObject_Dir(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_GetIter(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyIter_Next(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +Py_LT: t.CExtern | t.CInt | t.State +Py_LE: t.CExtern | t.CInt | t.State +Py_EQ: t.CExtern | t.CInt | t.State +Py_NE: t.CExtern | t.CInt | t.State +Py_GT: t.CExtern | t.CInt | t.State +Py_GE: t.CExtern | t.CInt | t.State + +def PyImport_ImportModule(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyImport_Import(name: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyImport_ImportModuleLevelObject(name: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr, level: t.CInt) -> PyObject | t.CPtr | t.State: pass + +def PyImport_ReloadModule(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyImport_AddModule(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyImport_GetModuleDict() -> PyObject | t.CPtr | t.State: pass + +def PyImport_ImportModuleEx(name: t.CConst | str, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +class PyMethodDef: + ml_name: t.CConst | str + ml_meth: t.CPtr + ml_flags: t.CInt + ml_doc: t.CConst | str +class PyModuleDef_Base: + ob_base: PyObject + m_init: t.CPtr + m_index: t.CSizeT + m_copy: PyObject | t.CPtr +class PyModuleDef: + m_base: PyModuleDef_Base + m_name: t.CConst | str + m_doc: t.CConst | str + m_size: t.CPtrDiffT + m_methods: PyMethodDef | t.CPtr + m_slots: t.CPtr + m_traverse: t.CPtr + m_clear: t.CPtr + m_free: t.CPtr + +def PyModule_Create(mod: PyModuleDef | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyModule_Create2(mod: PyModuleDef | t.CPtr, ver: t.CInt) -> PyObject | t.CPtr | t.State: pass + +def PyModule_GetName(mod: PyObject | t.CPtr) -> str | t.State: pass + +def PyModule_GetDict(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyModule_GetFilenameObject(mod: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyModule_AddObject(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyModule_AddObjectRef(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyModule_AddIntConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CLong) -> t.CInt | t.State: pass + +def PyModule_AddStringConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CConst | str) -> t.CInt | t.State: pass + +def PyGILState_Ensure() -> t.CInt | t.State: pass + +def PyGILState_Release(state: t.CInt) -> t.CVoid | t.State: pass + +def PyEval_SaveThread() -> t.CPtr | t.State: pass + +def PyEval_RestoreThread(tstate: t.CPtr) -> t.CVoid | t.State: pass + +def PyEval_AcquireThread(tstate: t.CPtr) -> t.CVoid | t.State: pass + +def PyEval_ReleaseThread(tstate: t.CPtr) -> t.CVoid | t.State: pass + +def PyEval_AcquireLock() -> t.CVoid | t.State: pass + +def PyEval_ReleaseLock() -> t.CVoid | t.State: pass + +def PyEval_ThreadsInitialized() -> t.CInt | t.State: pass + +def PyEval_InitThreads() -> t.CVoid | t.State: pass + +def PyErr_Occurred() -> PyObject | t.CPtr | t.State: pass + +def PyErr_Clear() -> t.CVoid | t.State: pass + +def PyErr_Fetch(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass + +def PyErr_Restore(tp: PyObject | t.CPtr, val: PyObject | t.CPtr, tb: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PyErr_NormalizeException(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr) -> t.CVoid | t.State: pass + +def PyErr_SetString(tp: PyObject | t.CPtr, msg: t.CConst | str) -> t.CVoid | t.State: pass + +def PyErr_SetObject(tp: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PyErr_BadArgument() -> t.CPtr | t.State: pass + +def PyErr_NoMemory() -> t.CPtr | t.State: pass + +def PyErr_Print() -> t.CVoid | t.State: pass + +def PyErr_ExceptionMatches(exc: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyErr_GivenExceptionMatches(given: PyObject | t.CPtr, exc: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +PyExc_BaseException: t.CExtern | PyObject | t.CPtr | t.State +PyExc_Exception: t.CExtern | PyObject | t.CPtr | t.State +PyExc_TypeError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_ValueError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_RuntimeError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_KeyError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_IndexError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_AttributeError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_ImportError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_OSError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_IOError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_ZeroDivisionError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_OverflowError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_MemoryError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_NameError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_StopIteration: t.CExtern | PyObject | t.CPtr | t.State +PyExc_NotImplementedError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_SyntaxError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_FileNotFoundError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_PermissionError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_IsADirectoryError: t.CExtern | PyObject | t.CPtr | t.State +PyExc_NotADirectoryError: t.CExtern | PyObject | t.CPtr | t.State + +def Py_BuildValue(fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def Py_VaBuildValue(fmt: t.CConst | str, va: t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyLong_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyFloat_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyUnicode_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyBytes_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyList_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyTuple_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyDict_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyBool_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyNone_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyMem_Malloc(size: t.CSizeT) -> t.CPtr | t.State: pass + +def PyMem_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr | t.State: pass + +def PyMem_Free(ptr: t.CPtr) -> t.CVoid | t.State: pass + +def PyMem_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr | t.State: pass + +def PyObject_Malloc(size: t.CSizeT) -> t.CPtr | t.State: pass + +def PyObject_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr | t.State: pass + +def PyObject_Free(ptr: t.CPtr) -> t.CVoid | t.State: pass + +def PyObject_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr | t.State: pass + +def PyObject_Init(obj: PyObject | t.CPtr, tp: t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyObject_InitVar(obj: PyObject | t.CPtr, tp: t.CPtr, size: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PyFile_FromString(filename: t.CConst | str, mode: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyFile_AsFile(file: PyObject | t.CPtr) -> t.CPtr | t.State: pass + +def PyFile_WriteObject(obj: PyObject | t.CPtr, file: PyObject | t.CPtr, flags: t.CInt) -> t.CInt | t.State: pass + +def PyFile_WriteString(s: t.CConst | str, file: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def Py_CompileString(s: t.CConst | str, filename: t.CConst | str, start: t.CInt) -> PyObject | t.CPtr | t.State: pass + +def PyEval_EvalCode(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyEval_EvalCodeEx(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, args: PyObject | t.CPtr | t.CPtr, argc: t.CInt, kws: PyObject | t.CPtr | t.CPtr, kwc: t.CInt, defs: PyObject | t.CPtr | t.CPtr, defc: t.CInt, kwdefs: PyObject | t.CPtr, closure: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyEval_EvalFrame(frame: t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyEval_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyEval_CallFunction(callable: PyObject | t.CPtr, fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyEval_CallMethod(obj: PyObject | t.CPtr, method: t.CConst | str, fmt: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyRun_SimpleString(cmd: t.CConst | str) -> t.CInt | t.State: pass + +def PyRun_SimpleFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt | t.State: pass + +def PyRun_AnyFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt | t.State: pass + +def PyRun_String(s: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyRun_File(fp: t.CPtr, filename: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + + +Py_single_input: t.CExtern | t.CInt | t.State +Py_file_input: t.CExtern | t.CInt | t.State +Py_eval_input: t.CExtern | t.CInt | t.State + +def PyCapsule_New(ptr: t.CPtr, name: t.CConst | str, dtor: t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyCapsule_GetPointer(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CPtr | t.State: pass + +def PyCapsule_GetName(cap: PyObject | t.CPtr) -> str | t.State: pass + +def PyCapsule_IsValid(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass + +def PyCapsule_SetPointer(cap: PyObject | t.CPtr, ptr: t.CPtr) -> t.CInt | t.State: pass + +def PyCapsule_SetName(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt | t.State: pass + +def PyCapsule_SetDestructor(cap: PyObject | t.CPtr, dtor: t.CPtr) -> t.CInt | t.State: pass + +def PySequence_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySequence_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PySequence_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PySequence_Concat(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PySequence_Repeat(obj: PyObject | t.CPtr, count: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PySequence_GetItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PySequence_SetItem(obj: PyObject | t.CPtr, idx: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySequence_DelItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CInt | t.State: pass + +def PySequence_GetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> PyObject | t.CPtr | t.State: pass + +def PySequence_SetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySequence_DelSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> t.CInt | t.State: pass + +def PySequence_Contains(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySequence_Index(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PySequence_Count(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PySequence_List(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PySequence_Tuple(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyMapping_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyMapping_Size(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyMapping_Length(obj: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PyMapping_HasKey(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyMapping_HasKeyString(obj: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt | t.State: pass + +def PyMapping_GetItemString(obj: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PyMapping_SetItemString(obj: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyMapping_Keys(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyMapping_Values(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyMapping_Items(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Add(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Subtract(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Multiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_MatrixMultiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_FloorDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_TrueDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Modulo(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Power(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, o3: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Negative(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Positive(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Absolute(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Invert(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Lshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Rshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_And(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Xor(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Or(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Index(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Long(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Float(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyNumber_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyWeakref_NewRef(obj: PyObject | t.CPtr, cb: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyWeakref_GetObject(ref: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyWeakref_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +class PyGetSetDef: + name: t.CConst | str + get: t.CPtr + set: t.CPtr + doc: t.CConst | str + closure: t.CPtr +class PyMemberDef: + name: t.CConst | str + type: t.CInt + offset: t.CPtrDiffT + flags: t.CInt + doc: t.CConst | str + +def PySys_GetObject(name: t.CConst | str) -> PyObject | t.CPtr | t.State: pass + +def PySys_SetObject(name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySys_ResetWarnOptions() -> t.CVoid | t.State: pass + +def PySys_AddWarnOption(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PySYS_AddXOption(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PySys_WriteStdout(fmt: t.CConst | str) -> t.CVoid | t.State: pass + +def PySys_WriteStderr(fmt: t.CConst | str) -> t.CVoid | t.State: pass + +def PySys_FormatStdout(fmt: t.CConst | str) -> t.CVoid | t.State: pass + +def PySys_FormatStderr(fmt: t.CConst | str) -> t.CVoid | t.State: pass + +def PyMemoryView_FromObject(obj: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyMemoryView_GetContiguous(obj: PyObject | t.CPtr, btype: t.CInt, order: t.CChar) -> PyObject | t.CPtr | t.State: pass + +def PyMemoryView_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PySet_Add(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySet_Discard(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySet_Contains(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySet_Size(s: PyObject | t.CPtr) -> t.CSizeT | t.State: pass + +def PySet_Clear(s: PyObject | t.CPtr) -> t.CVoid | t.State: pass + +def PySet_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PyFrozenSet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PyFrozenSet_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + +def PySlice_New(start: PyObject | t.CPtr, stop: PyObject | t.CPtr, step: PyObject | t.CPtr) -> PyObject | t.CPtr | t.State: pass + +def PySlice_GetIndicesEx(sl: PyObject | t.CPtr, length: t.CSizeT, start: t.CSizeT | t.CPtr, stop: t.CSizeT | t.CPtr, step: t.CSizeT | t.CPtr, slicelen: t.CSizeT | t.CPtr) -> t.CInt | t.State: pass + +def PySlice_Unpack(sl: PyObject | t.CPtr, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT | t.CPtr) -> t.CVoid | t.State: pass + +def PySlice_AdjustIndices(length: t.CSizeT, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT) -> t.CSizeT | t.State: pass + +def PySlice_Check(obj: PyObject | t.CPtr) -> t.CInt | t.State: pass + + +class PyLongObj: + ptr: PyObject | t.CPtr + def __new__(self: PyLongObj) -> 'PyLongObj' | t.CPtr: pass + @staticmethod + def from_long(val: t.CLong) -> 'PyLongObj' | t.CPtr: pass + def __add__(self: PyLongObj, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: pass + def __sub__(self: PyLongObj, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: pass + def __mul__(self: PyLongObj, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr: pass + def __neg__(self: PyLongObj) -> 'PyLongObj' | t.CPtr: pass + def to_long(self: PyLongObj) -> t.CLong: pass + def __str__(self: PyLongObj) -> PyObject | t.CPtr: pass + def dec_ref(self: PyLongObj) -> t.CInt: pass +class PyFloatObj: + ptr: PyObject | t.CPtr + def __new__(self: PyFloatObj) -> 'PyFloatObj' | t.CPtr: pass + @staticmethod + def from_double(val: t.CDouble) -> 'PyFloatObj' | t.CPtr: pass + def __add__(self: PyFloatObj, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: pass + def __sub__(self: PyFloatObj, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: pass + def __mul__(self: PyFloatObj, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: pass + def __truediv__(self: PyFloatObj, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr: pass + def __neg__(self: PyFloatObj) -> 'PyFloatObj' | t.CPtr: pass + def to_double(self: PyFloatObj) -> t.CDouble: pass + def __str__(self: PyFloatObj) -> PyObject | t.CPtr: pass + def dec_ref(self: PyFloatObj) -> t.CInt: pass +class PyUnicodeObj: + ptr: PyObject | t.CPtr + def __new__(self: PyUnicodeObj) -> 'PyUnicodeObj' | t.CPtr: pass + @staticmethod + def from_string(s: t.CChar | t.CPtr) -> 'PyUnicodeObj' | t.CPtr: pass + def __add__(self: PyUnicodeObj, other: PyUnicodeObj | t.CPtr) -> 'PyUnicodeObj' | t.CPtr: pass + def __len__(self: PyUnicodeObj) -> t.CPtrDiffT: pass + def as_utf8(self: PyUnicodeObj) -> t.CChar | t.CPtr: pass + def __str__(self: PyUnicodeObj) -> PyObject | t.CPtr: pass + def dec_ref(self: PyUnicodeObj) -> t.CInt: pass +class PyListObj: + ptr: PyObject | t.CPtr + def __new__(self: PyListObj) -> 'PyListObj' | t.CPtr: pass + @staticmethod + def new() -> 'PyListObj' | t.CPtr: pass + def __getitem__(self: PyListObj, idx: t.CSizeT) -> PyObject | t.CPtr: pass + def __setitem__(self: PyListObj, idx: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt: pass + def __len__(self: PyListObj) -> t.CSizeT: pass + def append(self: PyListObj, item: PyObject | t.CPtr) -> t.CInt: pass + def dec_ref(self: PyListObj) -> t.CInt: pass +class PyDictObj: + ptr: PyObject | t.CPtr + def __new__(self: PyDictObj) -> 'PyDictObj' | t.CPtr: pass + @staticmethod + def new() -> 'PyDictObj' | t.CPtr: pass + def __getitem__(self: PyDictObj, key: PyObject | t.CPtr) -> PyObject | t.CPtr: pass + def __setitem__(self: PyDictObj, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt: pass + def __len__(self: PyDictObj) -> t.CSizeT: pass + def get_string(self: PyDictObj, key: t.CChar | t.CPtr) -> PyObject | t.CPtr: pass + def set_string(self: PyDictObj, key: t.CChar | t.CPtr, val: PyObject | t.CPtr) -> t.CInt: pass + def dec_ref(self: PyDictObj) -> t.CInt: pass \ No newline at end of file diff --git a/Test/CPythonTest/temp/81ac26077a460417.pyi b/Test/CPythonTest/temp/81ac26077a460417.pyi deleted file mode 100644 index 0fadcf3..0000000 --- a/Test/CPythonTest/temp/81ac26077a460417.pyi +++ /dev/null @@ -1,20 +0,0 @@ -""" -Auto-generated Python stub file from stdarg.py -Module: stdarg -""" - -import c - - -import t - -def va_start(args: t.CPtr, last_arg: t.CPtr) -> t.State | t.CExtern | t.CExport: pass - -def va_arg(args: t.CPtr, type: t.CType) -> t.CType | t.CExtern | t.CExport | t.State: pass - -def va_end(args: t.CPtr) -> t.State | t.CExtern | t.CExport: pass - - -va_list: t.CTypedef = t.CUnsignedChar | t.CPtr - -def arg(type: t.CType) -> t.State | t.CExtern | t.CExport: pass diff --git a/Test/CPythonTest/temp/93131e2ff5450838.pyi b/Test/CPythonTest/temp/93131e2ff5450838.pyi deleted file mode 100644 index 1c3efa5..0000000 --- a/Test/CPythonTest/temp/93131e2ff5450838.pyi +++ /dev/null @@ -1,14 +0,0 @@ -""" -Auto-generated Python stub file from main.py -Module: main -""" - - -import t, c -from t import CInt, CPtr, CChar, CLong -import viperlib -import cpython - -def SetDllDirectoryA(lpPathName: str | CPtr) -> CInt | t.CExtern | t.State: pass - -def main() -> CInt | t.CExport | t.State: pass diff --git a/Test/CPythonTest/temp/_sha1_map.txt b/Test/CPythonTest/temp/_sha1_map.txt index cd326f1..8ac6cdb 100644 --- a/Test/CPythonTest/temp/_sha1_map.txt +++ b/Test/CPythonTest/temp/_sha1_map.txt @@ -1,6 +1,3 @@ -3e1c3f98e99cff7a:cpython.py -4d342c40331fc964:includes/viperlib.py -56cdd754a8a09347:includes/stdint.py -6999814920e8b3d5:main.py -81ac26077a460417:includes/stdarg.py -c9f4be41ca1cc2b4:includes/viperio.py +0cd580d62a3de4f8:main.py +73edbcf76e32d00b:includes/stdio.py +7c5d5ec59c5fb0a8:cpython.py diff --git a/Test/CPythonTest/temp/_shared_sym.pkl b/Test/CPythonTest/temp/_shared_sym.pkl index 7e4596b..1cea846 100644 Binary files a/Test/CPythonTest/temp/_shared_sym.pkl and b/Test/CPythonTest/temp/_shared_sym.pkl differ diff --git a/Test/CPythonTest/temp/c9f4be41ca1cc2b4.pyi b/Test/CPythonTest/temp/c9f4be41ca1cc2b4.pyi deleted file mode 100644 index b03434d..0000000 --- a/Test/CPythonTest/temp/c9f4be41ca1cc2b4.pyi +++ /dev/null @@ -1,22 +0,0 @@ -""" -Auto-generated Python stub file from viperio.py -Module: viperio -""" - - -import t, c -from stdint import * - -class Buf: - data: t.CChar | t.CPtr - length: t.CSizeT - capacity: t.CSizeT - owned: bool - def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CVoid | t.State: pass - def clear(self: Buf) -> t.CVoid | t.State: pass - def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT | t.State: pass - def cstr(self: Buf) -> t.CChar | t.CPtr | t.State: pass - def reset(self: Buf) -> t.CVoid | t.State: pass - def __enter__(self: Buf) -> 'Buf' | t.CPtr | t.State: pass - def __exit__(self: Buf) -> t.CVoid | t.State: pass - def free(self: Buf) -> t.CVoid | t.State: pass \ No newline at end of file diff --git a/Test/CPythonTest/temp/d771d4d68d9e75b3.pyi b/Test/CPythonTest/temp/d771d4d68d9e75b3.pyi deleted file mode 100644 index d986947..0000000 --- a/Test/CPythonTest/temp/d771d4d68d9e75b3.pyi +++ /dev/null @@ -1,17 +0,0 @@ -""" -Auto-generated Python stub file from viperio.py -Module: viperio -""" - - -import t, c - -@t.Object -class Buf: - buf: str - length: t.CSizeT - capacity: t.CSizeT - onHeap: bool - def __init__(self: Buf, buf: str, length: t.CSizeT, onHeap: bool) -> t.CVoid | t.State: pass - def free(self: Buf) -> t.CVoid | t.State: pass - def __del__(self: Buf) -> t.CVoid | t.State: pass \ No newline at end of file diff --git a/Test/IterTest/output/067c78e9f121dce3.deps.json b/Test/IterTest/output/067c78e9f121dce3.deps.json index 98471fa..195444b 100644 --- a/Test/IterTest/output/067c78e9f121dce3.deps.json +++ b/Test/IterTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/IterTest/output/29813d57621099a9.deps.json b/Test/IterTest/output/29813d57621099a9.deps.json index b357072..d74db22 100644 --- a/Test/IterTest/output/29813d57621099a9.deps.json +++ b/Test/IterTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/IterTest/output/5a6a2137958c28c5.deps.json b/Test/IterTest/output/5a6a2137958c28c5.deps.json index 1eabf36..b496ae1 100644 --- a/Test/IterTest/output/5a6a2137958c28c5.deps.json +++ b/Test/IterTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/IterTest/output/6aee24fdefa3cbc0.deps.json b/Test/IterTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..9295a3b --- /dev/null +++ b/Test/IterTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6"} \ No newline at end of file diff --git a/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json b/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json index 14389ed..2d1464a 100644 --- a/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/IterTest/output/73a525067569932e.deps.json b/Test/IterTest/output/73a525067569932e.deps.json deleted file mode 100644 index 4370328..0000000 --- a/Test/IterTest/output/73a525067569932e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6"} \ No newline at end of file diff --git a/Test/IterTest/output/abf9ce3160c9279e.deps.json b/Test/IterTest/output/abf9ce3160c9279e.deps.json index 14389ed..2d1464a 100644 --- a/Test/IterTest/output/abf9ce3160c9279e.deps.json +++ b/Test/IterTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json index a483152..3ce09e1 100644 --- a/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/IterTest/output/d044f813487c68b6.deps.json b/Test/IterTest/output/d044f813487c68b6.deps.json index b6c5f72..67944fb 100644 --- a/Test/IterTest/output/d044f813487c68b6.deps.json +++ b/Test/IterTest/output/d044f813487c68b6.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/IterTest/output/fa3691e66b426950.deps.json b/Test/IterTest/output/fa3691e66b426950.deps.json index 1eabf36..b496ae1 100644 --- a/Test/IterTest/output/fa3691e66b426950.deps.json +++ b/Test/IterTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "string": "73a525067569932e", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StringIterTest/temp/4d5db7f970ef510f.pyi b/Test/IterTest/temp/6aee24fdefa3cbc0.pyi similarity index 93% rename from Test/StringIterTest/temp/4d5db7f970ef510f.pyi rename to Test/IterTest/temp/6aee24fdefa3cbc0.pyi index eae6834..c17475f 100644 --- a/Test/StringIterTest/temp/4d5db7f970ef510f.pyi +++ b/Test/IterTest/temp/6aee24fdefa3cbc0.pyi @@ -37,4 +37,8 @@ def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.C def atoi(src: str) -> t.CInt: pass +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/IterTest/temp/_sha1_map.txt b/Test/IterTest/temp/_sha1_map.txt index 5b02c88..bfcb886 100644 --- a/Test/IterTest/temp/_sha1_map.txt +++ b/Test/IterTest/temp/_sha1_map.txt @@ -1,6 +1,6 @@ 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py -73a525067569932e:includes/string.py 73edbcf76e32d00b:includes/stdio.py d044f813487c68b6:main.py diff --git a/Test/JsonTest/output/68c4fe4b12c908e3.deps.json b/Test/JsonTest/output/68c4fe4b12c908e3.deps.json index 796afbb..2a07779 100644 --- a/Test/JsonTest/output/68c4fe4b12c908e3.deps.json +++ b/Test/JsonTest/output/68c4fe4b12c908e3.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/8ee3170049c70333.deps.json b/Test/JsonTest/output/8ee3170049c70333.deps.json index 796afbb..2a07779 100644 --- a/Test/JsonTest/output/8ee3170049c70333.deps.json +++ b/Test/JsonTest/output/8ee3170049c70333.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/bd2e7db1744476fe.deps.json b/Test/JsonTest/output/bd2e7db1744476fe.deps.json index 796afbb..2a07779 100644 --- a/Test/JsonTest/output/bd2e7db1744476fe.deps.json +++ b/Test/JsonTest/output/bd2e7db1744476fe.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json b/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json index 796afbb..2a07779 100644 --- a/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json +++ b/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/PointerTest/output/067c78e9f121dce3.deps.json b/Test/PointerTest/output/067c78e9f121dce3.deps.json index 998d71f..d127b4f 100644 --- a/Test/PointerTest/output/067c78e9f121dce3.deps.json +++ b/Test/PointerTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/PointerTest/output/29813d57621099a9.deps.json b/Test/PointerTest/output/29813d57621099a9.deps.json index b446460..2104859 100644 --- a/Test/PointerTest/output/29813d57621099a9.deps.json +++ b/Test/PointerTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/PointerTest/output/5a6a2137958c28c5.deps.json b/Test/PointerTest/output/5a6a2137958c28c5.deps.json index 04173c7..e0323b2 100644 --- a/Test/PointerTest/output/5a6a2137958c28c5.deps.json +++ b/Test/PointerTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/PointerTest/output/4d5db7f970ef510f.deps.json b/Test/PointerTest/output/6aee24fdefa3cbc0.deps.json similarity index 62% rename from Test/PointerTest/output/4d5db7f970ef510f.deps.json rename to Test/PointerTest/output/6aee24fdefa3cbc0.deps.json index 13ff2b2..ee07c04 100644 --- a/Test/PointerTest/output/4d5db7f970ef510f.deps.json +++ b/Test/PointerTest/output/6aee24fdefa3cbc0.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3"} \ No newline at end of file diff --git a/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json b/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json index 8c29b5d..eb46ab1 100644 --- a/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/PointerTest/output/PointerTest.exe.tmp0 b/Test/PointerTest/output/PointerTest.exe.tmp0 deleted file mode 100644 index 1db13da..0000000 Binary files a/Test/PointerTest/output/PointerTest.exe.tmp0 and /dev/null differ diff --git a/Test/PointerTest/output/abf9ce3160c9279e.deps.json b/Test/PointerTest/output/abf9ce3160c9279e.deps.json index 8c29b5d..eb46ab1 100644 --- a/Test/PointerTest/output/abf9ce3160c9279e.deps.json +++ b/Test/PointerTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json index 04173c7..e0323b2 100644 --- a/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/PointerTest/output/e0c894447ac34ed3.deps.json b/Test/PointerTest/output/e0c894447ac34ed3.deps.json index 1965c34..2fc9271 100644 --- a/Test/PointerTest/output/e0c894447ac34ed3.deps.json +++ b/Test/PointerTest/output/e0c894447ac34ed3.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/fa3691e66b426950.deps.json b/Test/PointerTest/output/fa3691e66b426950.deps.json index 04173c7..e0323b2 100644 --- a/Test/PointerTest/output/fa3691e66b426950.deps.json +++ b/Test/PointerTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/IterTest/temp/73a525067569932e.pyi b/Test/PointerTest/temp/6aee24fdefa3cbc0.pyi similarity index 93% rename from Test/IterTest/temp/73a525067569932e.pyi rename to Test/PointerTest/temp/6aee24fdefa3cbc0.pyi index eae6834..c17475f 100644 --- a/Test/IterTest/temp/73a525067569932e.pyi +++ b/Test/PointerTest/temp/6aee24fdefa3cbc0.pyi @@ -37,4 +37,8 @@ def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.C def atoi(src: str) -> t.CInt: pass +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/PointerTest/temp/_sha1_map.txt b/Test/PointerTest/temp/_sha1_map.txt index 46d0124..ce6bb1a 100644 --- a/Test/PointerTest/temp/_sha1_map.txt +++ b/Test/PointerTest/temp/_sha1_map.txt @@ -1,6 +1,6 @@ -4d5db7f970ef510f:includes/string.py 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py bbdf3bbd4c3bc28c:includes/w32\win32console.py diff --git a/Test/ReTest/output/68c4fe4b12c908e3.deps.json b/Test/ReTest/output/68c4fe4b12c908e3.deps.json new file mode 100644 index 0000000..185e2d9 --- /dev/null +++ b/Test/ReTest/output/68c4fe4b12c908e3.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "re.__init__": "839e950555b6a435", "__init__": "839e950555b6a435", "re": "839e950555b6a435", "main": "9ef80c98cfbbce42", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/ReTest/output/6aee24fdefa3cbc0.deps.json b/Test/ReTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..185e2d9 --- /dev/null +++ b/Test/ReTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "re.__init__": "839e950555b6a435", "__init__": "839e950555b6a435", "re": "839e950555b6a435", "main": "9ef80c98cfbbce42", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/ReTest/output/839e950555b6a435.deps.json b/Test/ReTest/output/839e950555b6a435.deps.json new file mode 100644 index 0000000..185e2d9 --- /dev/null +++ b/Test/ReTest/output/839e950555b6a435.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "re.__init__": "839e950555b6a435", "__init__": "839e950555b6a435", "re": "839e950555b6a435", "main": "9ef80c98cfbbce42", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/ReTest/output/9ef80c98cfbbce42.deps.json b/Test/ReTest/output/9ef80c98cfbbce42.deps.json new file mode 100644 index 0000000..4b6a540 --- /dev/null +++ b/Test/ReTest/output/9ef80c98cfbbce42.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "re.__init__": "839e950555b6a435", "__init__": "839e950555b6a435", "re": "839e950555b6a435", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/ReTest/output/c9f4be41ca1cc2b4.deps.json b/Test/ReTest/output/c9f4be41ca1cc2b4.deps.json new file mode 100644 index 0000000..185e2d9 --- /dev/null +++ b/Test/ReTest/output/c9f4be41ca1cc2b4.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "re.__init__": "839e950555b6a435", "__init__": "839e950555b6a435", "re": "839e950555b6a435", "main": "9ef80c98cfbbce42", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/CPythonTest/temp/56cdd754a8a09347.pyi b/Test/ReTest/temp/56cdd754a8a09347.pyi similarity index 100% rename from Test/CPythonTest/temp/56cdd754a8a09347.pyi rename to Test/ReTest/temp/56cdd754a8a09347.pyi diff --git a/Test/TestProject3/temp/21ffad37f6fc3fcf.pyi b/Test/ReTest/temp/68c4fe4b12c908e3.pyi similarity index 67% rename from Test/TestProject3/temp/21ffad37f6fc3fcf.pyi rename to Test/ReTest/temp/68c4fe4b12c908e3.pyi index f237768..fc2010b 100644 --- a/Test/TestProject3/temp/21ffad37f6fc3fcf.pyi +++ b/Test/ReTest/temp/68c4fe4b12c908e3.pyi @@ -28,17 +28,23 @@ class MPool: free_list: t.CVoid | t.CPtr alloc_map: t.CUInt8T | t.CPtr alloc_map_size: t.CSizeT - def __init__(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CVoid: pass - def _init_bump(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> t.CVoid: pass - def _init_slab(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CVoid: pass + def __init__(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass + def _init_bump(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> t.CInt: pass + def _init_slab(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass def __enter__(self: MPool) -> 'MPool' | t.CPtr: pass - def __exit__(self: MPool) -> t.CVoid: pass - def _slab_reset(self: MPool) -> t.CVoid: pass + def __exit__(self: MPool) -> t.CInt: pass + def _slab_reset(self: MPool) -> t.CInt: pass def alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass def alloc_buf(self: MPool, capacity: t.CSizeT) -> viperio.Buf | t.CPtr: pass - def free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CVoid: pass + def free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass def realloc(self: MPool, ptr: t.CVoid | t.CPtr, old_size: t.CSizeT, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass - def reset(self: MPool) -> t.CVoid: pass + def reset(self: MPool) -> t.CInt: pass def _bump_alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass def _slab_alloc(self: MPool) -> t.CVoid | t.CPtr: pass - def _slab_free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CVoid: pass \ No newline at end of file + def _slab_free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + +def bump_create(mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> MPool | t.CPtr: pass + +def alloc(pool: MPool | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def reset(pool: MPool | t.CPtr) -> t.CInt: pass diff --git a/Test/PointerTest/temp/4d5db7f970ef510f.pyi b/Test/ReTest/temp/6aee24fdefa3cbc0.pyi similarity index 93% rename from Test/PointerTest/temp/4d5db7f970ef510f.pyi rename to Test/ReTest/temp/6aee24fdefa3cbc0.pyi index eae6834..c17475f 100644 --- a/Test/PointerTest/temp/4d5db7f970ef510f.pyi +++ b/Test/ReTest/temp/6aee24fdefa3cbc0.pyi @@ -37,4 +37,8 @@ def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.C def atoi(src: str) -> t.CInt: pass +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/ReTest/temp/73edbcf76e32d00b.pyi b/Test/ReTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/ReTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/SimdTest/temp/7538e542cab4c1d5.pyi b/Test/ReTest/temp/7538e542cab4c1d5.pyi similarity index 100% rename from Test/SimdTest/temp/7538e542cab4c1d5.pyi rename to Test/ReTest/temp/7538e542cab4c1d5.pyi diff --git a/Test/ReTest/temp/839e950555b6a435.pyi b/Test/ReTest/temp/839e950555b6a435.pyi new file mode 100644 index 0000000..4440462 --- /dev/null +++ b/Test/ReTest/temp/839e950555b6a435.pyi @@ -0,0 +1,103 @@ +""" +Auto-generated Python stub file from re.__init__.py +Module: re.__init__ +""" + + +import t, c +from stdint import * +import mpool +import string + +RE_CHAR: t.CDefine = 0 # 匹配单个字符 +RE_DOT: t.CDefine = 1 # 匹配任意字符(除换行) +RE_CLASS: t.CDefine = 2 # 匹配字符类 [abc] +RE_NCLASS: t.CDefine = 3 # 匹配反义字符类 [^abc] +RE_SPLIT: t.CDefine = 4 # 分裂节点(用于 | ? *) +RE_JUMP: t.CDefine = 5 # 无条件跳转(用于连接) +RE_MATCH: t.CDefine = 6 # 匹配成功 +RE_BOL: t.CDefine = 7 # 行首 ^ +RE_EOL: t.CDefine = 8 # 行尾 $ +RE_DCLASS: t.CDefine = 9 # 预定义字符类 \d \w \s +RE_NDCLASS: t.CDefine = 10 # 预定义反义字符类 \D \W \S +DCLASS_DIGIT: t.CDefine = 0 # \d +DCLASS_WORD: t.CDefine = 1 # \w +DCLASS_SPACE: t.CDefine = 2 # \s +RE_MAX_NODES: t.CDefine = 256 +RE_MAX_STATES: t.CDefine = 256 + +class Renode: + ntype: t.CInt + ch: t.CChar + out1: Renode | t.CPtr + out2: Renode | t.CPtr + cls: t.CChar | t.CPtr + dcls: t.CInt + def __new__(self: Renode, pool: mpool.MPool | t.CPtr) -> 'Renode' | t.CPtr: pass +class RePtrList: + node: Renode | t.CPtr + which: t.CInt + next: RePtrList | t.CPtr + def __new__(self: RePtrList, pool: mpool.MPool | t.CPtr) -> 'RePtrList' | t.CPtr: pass +class Refrag: + start: Renode | t.CPtr + out: RePtrList | t.CPtr + def __new__(self: Refrag, pool: mpool.MPool | t.CPtr) -> 'Refrag' | t.CPtr: pass +class Rematch: + start: t.CSizeT + end: t.CSizeT + found: t.CInt + def __new__(self: Rematch, pool: mpool.MPool | t.CPtr) -> 'Rematch' | t.CPtr: pass + +def _is_word_char(ch: t.CChar) -> bool: pass + +def _match_dclass(dcls: t.CInt, ch: t.CChar) -> bool: pass + +def _list_append(pool: mpool.MPool | t.CPtr, head: RePtrList | t.CPtr, node: Renode | t.CPtr, which: t.CInt) -> RePtrList | t.CPtr: pass + +def _list_patch(head: RePtrList | t.CPtr, target: Renode | t.CPtr) -> t.CInt: pass + +def _list_concat(a: RePtrList | t.CPtr, b: RePtrList | t.CPtr) -> RePtrList | t.CPtr: pass + + +class Recompiler: + pool: mpool.MPool | t.CPtr + p: t.CChar | t.CPtr + pend: t.CChar | t.CPtr + match_node: Renode | t.CPtr + def __new__(self: Recompiler, pool: mpool.MPool | t.CPtr) -> 'Recompiler' | t.CPtr: pass + def compile(self: Recompiler, pattern: t.CChar | t.CPtr) -> Renode | t.CPtr: pass + def _peek(self: Recompiler) -> t.CChar: pass + def _next(self: Recompiler) -> t.CChar: pass + def _parse_alt(self: Recompiler) -> Refrag | t.CPtr: pass + def _parse_concat(self: Recompiler) -> Refrag | t.CPtr: pass + def _parse_repeat(self: Recompiler) -> Refrag | t.CPtr: pass + def _parse_atom(self: Recompiler) -> Refrag | t.CPtr: pass + def _parse_escape(self: Recompiler) -> Refrag | t.CPtr: pass + def _parse_class(self: Recompiler) -> Refrag | t.CPtr: pass +class Restate: + node: Renode | t.CPtr + pos: t.CSizeT + def __new__(self: Restate, pool: mpool.MPool | t.CPtr) -> 'Restate' | t.CPtr: pass + +def _add_state(nlist: t.CVoid | t.CPtr, node: Renode | t.CPtr, pos: t.CSizeT, text: t.CChar | t.CPtr, nstates: t.CInt, max_states: t.CInt) -> t.CInt: pass + +def _read_node(slist: t.CVoid | t.CPtr, idx: t.CInt) -> Renode | t.CPtr: pass + +def _read_pos(slist: t.CVoid | t.CPtr, idx: t.CInt) -> t.CSizeT: pass + +def _step(clist: t.CVoid | t.CPtr, nlist: t.CVoid | t.CPtr, ch: t.CChar, pos: t.CSizeT, text: t.CChar | t.CPtr, cstates: t.CInt, max_states: t.CInt) -> t.CInt: pass + +def _check_match(slist: t.CVoid | t.CPtr, nstates: t.CInt) -> t.CSizeT: pass + +def compile(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr) -> Renode | t.CPtr: pass + +def match(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr, text: t.CChar | t.CPtr) -> Rematch | t.CPtr: pass + +def search(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr, text: t.CChar | t.CPtr) -> Rematch | t.CPtr: pass + +def findall(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr, text: t.CChar | t.CPtr, results: t.CChar | t.CPtr | t.CPtr, max_results: t.CSizeT) -> t.CSizeT: pass + +def sub(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr, replacement: t.CChar | t.CPtr, text: t.CChar | t.CPtr, outbuf: t.CChar | t.CPtr, outsize: t.CSizeT) -> t.CSizeT: pass + +def split(pool: mpool.MPool | t.CPtr, pattern: t.CChar | t.CPtr, text: t.CChar | t.CPtr, results: t.CChar | t.CPtr | t.CPtr, max_results: t.CSizeT) -> t.CSizeT: pass diff --git a/Test/ReTest/temp/9ef80c98cfbbce42.pyi b/Test/ReTest/temp/9ef80c98cfbbce42.pyi new file mode 100644 index 0000000..dc5715e --- /dev/null +++ b/Test/ReTest/temp/9ef80c98cfbbce42.pyi @@ -0,0 +1,58 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +import t, c +from t import CInt, CLong, CDouble, CPtr, CSizeT, CChar +from stdio import printf +import re +import mpool +import string +import stdlib + +_pass_count: t.CExtern | CInt +_fail_count: t.CExtern | CInt + +def check(name: CChar | CPtr, condition: bool) -> t.CInt: pass + +def make_pool() -> mpool.MPool | CPtr: pass + +def free_pool(pool: mpool.MPool | CPtr) -> t.CInt: pass + +def test_basic_match() -> t.CInt: pass + +def test_dot() -> t.CInt: pass + +def test_star() -> t.CInt: pass + +def test_plus() -> t.CInt: pass + +def test_question() -> t.CInt: pass + +def test_alt() -> t.CInt: pass + +def test_group() -> t.CInt: pass + +def test_charclass() -> t.CInt: pass + +def test_predefined() -> t.CInt: pass + +def test_search() -> t.CInt: pass + +def test_findall() -> t.CInt: pass + +def test_sub() -> t.CInt: pass + +def test_split() -> t.CInt: pass + +def test_anchors() -> t.CInt: pass + +def test_escape() -> t.CInt: pass + +def test_mpool_reuse() -> t.CInt: pass + +def test_complex() -> t.CInt: pass + +def main() -> t.CInt: pass diff --git a/Test/ReTest/temp/_sha1_map.txt b/Test/ReTest/temp/_sha1_map.txt new file mode 100644 index 0000000..6ff19cc --- /dev/null +++ b/Test/ReTest/temp/_sha1_map.txt @@ -0,0 +1,8 @@ +56cdd754a8a09347:includes/stdint.py +68c4fe4b12c908e3:includes/mpool.py +6aee24fdefa3cbc0:includes/string.py +73edbcf76e32d00b:includes/stdio.py +7538e542cab4c1d5:includes/stdlib.py +839e950555b6a435:includes/re\__init__.py +9ef80c98cfbbce42:main.py +c9f4be41ca1cc2b4:includes/viperio.py diff --git a/Test/ReTest/temp/c9f4be41ca1cc2b4.pyi b/Test/ReTest/temp/c9f4be41ca1cc2b4.pyi new file mode 100644 index 0000000..fdbd7ec --- /dev/null +++ b/Test/ReTest/temp/c9f4be41ca1cc2b4.pyi @@ -0,0 +1,22 @@ +""" +Auto-generated Python stub file from viperio.py +Module: viperio +""" + + +import t, c +from stdint import * + +class Buf: + data: t.CChar | t.CPtr + length: t.CSizeT + capacity: t.CSizeT + owned: bool + def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass + def clear(self: Buf) -> t.CInt: pass + def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass + def cstr(self: Buf) -> t.CChar | t.CPtr: pass + def reset(self: Buf) -> t.CInt: pass + def __enter__(self: Buf) -> 'Buf' | t.CPtr: pass + def __exit__(self: Buf) -> t.CInt: pass + def free(self: Buf) -> t.CInt: pass \ No newline at end of file diff --git a/Test/SimdTest/output/024a3459d0f585ae.deps.json b/Test/SimdTest/output/024a3459d0f585ae.deps.json deleted file mode 100644 index 3ad8593..0000000 --- a/Test/SimdTest/output/024a3459d0f585ae.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/1b666d438f4d301e.deps.json b/Test/SimdTest/output/1b666d438f4d301e.deps.json index f4ea96d..0fec052 100644 --- a/Test/SimdTest/output/1b666d438f4d301e.deps.json +++ b/Test/SimdTest/output/1b666d438f4d301e.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/3f7c5e78d8652535.deps.json b/Test/SimdTest/output/3f7c5e78d8652535.deps.json index 3ad8593..6c27984 100644 --- a/Test/SimdTest/output/3f7c5e78d8652535.deps.json +++ b/Test/SimdTest/output/3f7c5e78d8652535.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/68c4fe4b12c908e3.deps.json b/Test/SimdTest/output/68c4fe4b12c908e3.deps.json index 3ad8593..6c27984 100644 --- a/Test/SimdTest/output/68c4fe4b12c908e3.deps.json +++ b/Test/SimdTest/output/68c4fe4b12c908e3.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json b/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..6c27984 --- /dev/null +++ b/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/c3eb91093118e1e1.deps.json b/Test/SimdTest/output/c3eb91093118e1e1.deps.json index 3ad8593..6c27984 100644 --- a/Test/SimdTest/output/c3eb91093118e1e1.deps.json +++ b/Test/SimdTest/output/c3eb91093118e1e1.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json b/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json index 3ad8593..6c27984 100644 --- a/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/fe99c83946298690.deps.json b/Test/SimdTest/output/fe99c83946298690.deps.json index 3ad8593..6c27984 100644 --- a/Test/SimdTest/output/fe99c83946298690.deps.json +++ b/Test/SimdTest/output/fe99c83946298690.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/temp/024a3459d0f585ae.pyi b/Test/SimdTest/temp/6aee24fdefa3cbc0.pyi similarity index 93% rename from Test/SimdTest/temp/024a3459d0f585ae.pyi rename to Test/SimdTest/temp/6aee24fdefa3cbc0.pyi index eae6834..c17475f 100644 --- a/Test/SimdTest/temp/024a3459d0f585ae.pyi +++ b/Test/SimdTest/temp/6aee24fdefa3cbc0.pyi @@ -37,4 +37,8 @@ def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.C def atoi(src: str) -> t.CInt: pass +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/SimdTest/temp/6c2029b306556c00.pyi b/Test/SimdTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/SimdTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/SimdTest/temp/_sha1_map.txt b/Test/SimdTest/temp/_sha1_map.txt index 8dd8e2c..e9909af 100644 --- a/Test/SimdTest/temp/_sha1_map.txt +++ b/Test/SimdTest/temp/_sha1_map.txt @@ -1,10 +1,10 @@ -024a3459d0f585ae:includes/string.py 1b666d438f4d301e:main.py 3f7c5e78d8652535:includes/vipermath.py 56cdd754a8a09347:includes/stdint.py 68c4fe4b12c908e3:includes/mpool.py +6aee24fdefa3cbc0:includes/string.py +6c2029b306556c00:includes/stdlib.py 73edbcf76e32d00b:includes/stdio.py -7538e542cab4c1d5:includes/stdlib.py c3eb91093118e1e1:includes/numpy\__init__.py c9f4be41ca1cc2b4:includes/viperio.py fe99c83946298690:includes/vipersimd.py diff --git a/Test/StringIterTest/output/2255fdda7aed5595.deps.json b/Test/StringIterTest/output/2255fdda7aed5595.deps.json index 77fa018..edd3f31 100644 --- a/Test/StringIterTest/output/2255fdda7aed5595.deps.json +++ b/Test/StringIterTest/output/2255fdda7aed5595.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringIterTest/output/4d5db7f970ef510f.deps.json b/Test/StringIterTest/output/4d5db7f970ef510f.deps.json deleted file mode 100644 index 07c20ae..0000000 --- a/Test/StringIterTest/output/4d5db7f970ef510f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "2255fdda7aed5595", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json b/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..f246770 --- /dev/null +++ b/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"main": "2255fdda7aed5595", "stdint": "56cdd754a8a09347", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi b/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StringIterTest/temp/_sha1_map.txt b/Test/StringIterTest/temp/_sha1_map.txt index 856d8cc..c04ac36 100644 --- a/Test/StringIterTest/temp/_sha1_map.txt +++ b/Test/StringIterTest/temp/_sha1_map.txt @@ -1,4 +1,4 @@ 2255fdda7aed5595:main.py -4d5db7f970ef510f:includes/string.py 56cdd754a8a09347:includes/stdint.py +6aee24fdefa3cbc0:includes/string.py 73edbcf76e32d00b:includes/stdio.py diff --git a/Test/StringTest/output/067c78e9f121dce3.deps.json b/Test/StringTest/output/067c78e9f121dce3.deps.json index 438a5c0..df05eb5 100644 --- a/Test/StringTest/output/067c78e9f121dce3.deps.json +++ b/Test/StringTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/StringTest/output/29813d57621099a9.deps.json b/Test/StringTest/output/29813d57621099a9.deps.json index cd6c7b8..8cd5685 100644 --- a/Test/StringTest/output/29813d57621099a9.deps.json +++ b/Test/StringTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/StringTest/output/5a6a2137958c28c5.deps.json b/Test/StringTest/output/5a6a2137958c28c5.deps.json index f00af17..f330458 100644 --- a/Test/StringTest/output/5a6a2137958c28c5.deps.json +++ b/Test/StringTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StringTest/output/4d5db7f970ef510f.deps.json b/Test/StringTest/output/6aee24fdefa3cbc0.deps.json similarity index 50% rename from Test/StringTest/output/4d5db7f970ef510f.deps.json rename to Test/StringTest/output/6aee24fdefa3cbc0.deps.json index a36f7d0..3ad7aab 100644 --- a/Test/StringTest/output/4d5db7f970ef510f.deps.json +++ b/Test/StringTest/output/6aee24fdefa3cbc0.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a"} \ No newline at end of file diff --git a/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json b/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json index 5017b39..21877dd 100644 --- a/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StringTest/output/7aa13c104a22528a.deps.json b/Test/StringTest/output/7aa13c104a22528a.deps.json index 7ea28c1..67944fb 100644 --- a/Test/StringTest/output/7aa13c104a22528a.deps.json +++ b/Test/StringTest/output/7aa13c104a22528a.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringTest/output/abf9ce3160c9279e.deps.json b/Test/StringTest/output/abf9ce3160c9279e.deps.json index 5017b39..21877dd 100644 --- a/Test/StringTest/output/abf9ce3160c9279e.deps.json +++ b/Test/StringTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json index 2138712..3b37a69 100644 --- a/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/StringTest/output/fa3691e66b426950.deps.json b/Test/StringTest/output/fa3691e66b426950.deps.json index f00af17..f330458 100644 --- a/Test/StringTest/output/fa3691e66b426950.deps.json +++ b/Test/StringTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StringTest/temp/4d5db7f970ef510f.pyi b/Test/StringTest/temp/4d5db7f970ef510f.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/StringTest/temp/4d5db7f970ef510f.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StringTest/temp/6aee24fdefa3cbc0.pyi b/Test/StringTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/StringTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StringTest/temp/_sha1_map.txt b/Test/StringTest/temp/_sha1_map.txt index 9bb1406..c52b3e4 100644 --- a/Test/StringTest/temp/_sha1_map.txt +++ b/Test/StringTest/temp/_sha1_map.txt @@ -1,6 +1,6 @@ -4d5db7f970ef510f:includes/string.py 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py 7aa13c104a22528a:main.py diff --git a/Test/StructTest/output/067c78e9f121dce3.deps.json b/Test/StructTest/output/067c78e9f121dce3.deps.json index 19c4010..b1872c1 100644 --- a/Test/StructTest/output/067c78e9f121dce3.deps.json +++ b/Test/StructTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/StructTest/output/29813d57621099a9.deps.json b/Test/StructTest/output/29813d57621099a9.deps.json index e6e2b5c..361ae76 100644 --- a/Test/StructTest/output/29813d57621099a9.deps.json +++ b/Test/StructTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/StructTest/output/5a6a2137958c28c5.deps.json b/Test/StructTest/output/5a6a2137958c28c5.deps.json index dab5750..61bb2b5 100644 --- a/Test/StructTest/output/5a6a2137958c28c5.deps.json +++ b/Test/StructTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StructTest/output/6aee24fdefa3cbc0.deps.json b/Test/StructTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..ccd7f6c --- /dev/null +++ b/Test/StructTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StructTest/output/6f6ee14c129ac228.deps.json b/Test/StructTest/output/6f6ee14c129ac228.deps.json index 9ec9abe..67944fb 100644 --- a/Test/StructTest/output/6f6ee14c129ac228.deps.json +++ b/Test/StructTest/output/6f6ee14c129ac228.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json b/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json index 29cf064..d136494 100644 --- a/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StructTest/output/a326a52b7c4bd6f0.deps.json b/Test/StructTest/output/a326a52b7c4bd6f0.deps.json deleted file mode 100644 index 1b0fb2d..0000000 --- a/Test/StructTest/output/a326a52b7c4bd6f0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0"} \ No newline at end of file diff --git a/Test/StructTest/output/abf9ce3160c9279e.deps.json b/Test/StructTest/output/abf9ce3160c9279e.deps.json index 29cf064..d136494 100644 --- a/Test/StructTest/output/abf9ce3160c9279e.deps.json +++ b/Test/StructTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json index 4f819ec..cbfaa63 100644 --- a/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/StructTest/output/fa3691e66b426950.deps.json b/Test/StructTest/output/fa3691e66b426950.deps.json index dab5750..61bb2b5 100644 --- a/Test/StructTest/output/fa3691e66b426950.deps.json +++ b/Test/StructTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StructTest/temp/6aee24fdefa3cbc0.pyi b/Test/StructTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/StructTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StructTest/temp/_sha1_map.txt b/Test/StructTest/temp/_sha1_map.txt index 1fa7b41..af6559c 100644 --- a/Test/StructTest/temp/_sha1_map.txt +++ b/Test/StructTest/temp/_sha1_map.txt @@ -1,6 +1,6 @@ 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 6f6ee14c129ac228:main.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -a326a52b7c4bd6f0:includes/string.py diff --git a/Test/StructTest/temp/a326a52b7c4bd6f0.pyi b/Test/StructTest/temp/a326a52b7c4bd6f0.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/StructTest/temp/a326a52b7c4bd6f0.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TestFBProject/App/main.py b/Test/TestFBProject/App/main.py index c6e2804..e98256a 100644 --- a/Test/TestFBProject/App/main.py +++ b/Test/TestFBProject/App/main.py @@ -1,158 +1,158 @@ -from stdint import * -import w32.win32console -import t, c - - -def add_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - return a + b - -def mul_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - return a * b - - -class AppError(Exception): - pass - -class DiskError(AppError): - pass - -class NetworkError(AppError): - pass - -class TimeoutError(NetworkError): - pass - - -def raise_disk(): - raise DiskError("disk read failed") - -def raise_network(): - raise NetworkError("connection refused") - -def raise_timeout(): - raise TimeoutError("operation timed out") - - -def main() -> t.CInt | t.CExport: - w32.win32console.SetConsoleCP(65001) - w32.win32console.SetConsoleOutputCP(65001) - - print("=== Test 1: Raise and catch exact custom exception ===") - try: - raise DiskError("disk error") - except DiskError as e: - print("PASS 1: caught DiskError:", e) - except: - print("FAIL 1: caught by generic except") - print("") - - print("=== Test 2: Catch parent catches child ===") - try: - raise_disk() - except AppError as e: - print("PASS 2: caught AppError (child DiskError):", e) - except: - print("FAIL 2: caught by generic except") - print("") - - print("=== Test 3: Catch parent catches nested child ===") - try: - raise_timeout() - except AppError as e: - print("PASS 3: caught AppError (grandchild TimeoutError):", e) - except: - print("FAIL 3: caught by generic except") - print("") - - print("=== Test 4: Catch mid-level parent ===") - try: - raise_timeout() - except NetworkError as e: - print("PASS 4: caught NetworkError (child TimeoutError):", e) - except: - print("FAIL 4: caught by generic except") - print("") - - print("=== Test 5: Exact catch before parent ===") - try: - raise_network() - except NetworkError as e: - print("PASS 5: caught NetworkError:", e) - except AppError as e: - print("FAIL 5: caught AppError (should be NetworkError first)") - except: - print("FAIL 5: caught by generic except") - print("") - - print("=== Test 6: Parent catch when exact not present ===") - try: - raise_network() - except DiskError as e: - print("FAIL 6: caught DiskError (wrong)") - except AppError as e: - print("PASS 6: caught AppError (no NetworkError handler):", e) - except: - print("FAIL 6: caught by generic except") - print("") - - print("=== Test 7: Generic except fallback ===") - try: - raise_disk() - except RuntimeError as e: - print("FAIL 7: caught RuntimeError (wrong)") - except: - print("PASS 7: caught by generic except") - print("") - - print("=== Test 8: Cross-function with inheritance ===") - try: - raise_timeout() - except NetworkError as e: - print("PASS 8: caught NetworkError (cross-func TimeoutError):", e) - except: - print("FAIL 8: caught by generic except") - print("") - - print("=== Test 9: Built-in exception still works ===") - try: - raise ValueError("test") - except ValueError as e: - print("PASS 9: caught ValueError:", e) - except: - print("FAIL 9: caught by generic except") - print("") - - print("=== Test 10: Mixed built-in and custom ===") - try: - raise RuntimeError("test") - except DiskError as e: - print("FAIL 10: caught DiskError (wrong)") - except RuntimeError as e: - print("PASS 10: caught RuntimeError:", e) - except: - print("FAIL 10: caught by generic except") - print("") - - print("=== All Custom Exception Tests Complete ===") - - print("") - print("=== Test LLVMIR: inline LLVM IR add ===") - x: t.CInt = 10 - y: t.CInt = 20 - r: t.CInt = c.LLVMIR(f"add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) - print("LLVMIR add result:", r) - - print("") - print("=== Test CDefine function macro ===") - s: t.CInt = add_inline(3, 4) - print("add_inline(3, 4) =", s) - m: t.CInt = mul_inline(5, 6) - print("mul_inline(5, 6) =", m) - - print("") - print("=== Test LLVMIR with LOut ===") - out_val: t.CInt = 0 - c.LLVMIR(f"{c.LOut(out_val)} = add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) - print("LLVMIR LOut result:", out_val) - - return 0 +from stdint import * +import w32.win32console +import t, c + + +def add_inline(a: t.CInt, b: t.CInt) -> t.CDefine: + return a + b + +def mul_inline(a: t.CInt, b: t.CInt) -> t.CDefine: + return a * b + + +class AppError(Exception): + pass + +class DiskError(AppError): + pass + +class NetworkError(AppError): + pass + +class TimeoutError(NetworkError): + pass + + +def raise_disk(): + raise DiskError("disk read failed") + +def raise_network(): + raise NetworkError("connection refused") + +def raise_timeout(): + raise TimeoutError("operation timed out") + + +def main() -> t.CInt | t.CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + print("=== Test 1: Raise and catch exact custom exception ===") + try: + raise DiskError("disk error") + except DiskError as e: + print("PASS 1: caught DiskError:", e) + except: + print("FAIL 1: caught by generic except") + print("") + + print("=== Test 2: Catch parent catches child ===") + try: + raise_disk() + except AppError as e: + print("PASS 2: caught AppError (child DiskError):", e) + except: + print("FAIL 2: caught by generic except") + print("") + + print("=== Test 3: Catch parent catches nested child ===") + try: + raise_timeout() + except AppError as e: + print("PASS 3: caught AppError (grandchild TimeoutError):", e) + except: + print("FAIL 3: caught by generic except") + print("") + + print("=== Test 4: Catch mid-level parent ===") + try: + raise_timeout() + except NetworkError as e: + print("PASS 4: caught NetworkError (child TimeoutError):", e) + except: + print("FAIL 4: caught by generic except") + print("") + + print("=== Test 5: Exact catch before parent ===") + try: + raise_network() + except NetworkError as e: + print("PASS 5: caught NetworkError:", e) + except AppError as e: + print("FAIL 5: caught AppError (should be NetworkError first)") + except: + print("FAIL 5: caught by generic except") + print("") + + print("=== Test 6: Parent catch when exact not present ===") + try: + raise_network() + except DiskError as e: + print("FAIL 6: caught DiskError (wrong)") + except AppError as e: + print("PASS 6: caught AppError (no NetworkError handler):", e) + except: + print("FAIL 6: caught by generic except") + print("") + + print("=== Test 7: Generic except fallback ===") + try: + raise_disk() + except RuntimeError as e: + print("FAIL 7: caught RuntimeError (wrong)") + except: + print("PASS 7: caught by generic except") + print("") + + print("=== Test 8: Cross-function with inheritance ===") + try: + raise_timeout() + except NetworkError as e: + print("PASS 8: caught NetworkError (cross-func TimeoutError):", e) + except: + print("FAIL 8: caught by generic except") + print("") + + print("=== Test 9: Built-in exception still works ===") + try: + raise ValueError("test") + except ValueError as e: + print("PASS 9: caught ValueError:", e) + except: + print("FAIL 9: caught by generic except") + print("") + + print("=== Test 10: Mixed built-in and custom ===") + try: + raise RuntimeError("test") + except DiskError as e: + print("FAIL 10: caught DiskError (wrong)") + except RuntimeError as e: + print("PASS 10: caught RuntimeError:", e) + except: + print("FAIL 10: caught by generic except") + print("") + + print("=== All Custom Exception Tests Complete ===") + + print("") + print("=== Test LLVMIR: inline LLVM IR add ===") + x: t.CInt = 10 + y: t.CInt = 20 + r: t.CInt = c.LLVMIR(f"add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) + print("LLVMIR add result:", r) + + print("") + print("=== Test CDefine function macro ===") + s: t.CInt = add_inline(3, 4) + print("add_inline(3, 4) =", s) + m: t.CInt = mul_inline(5, 6) + print("mul_inline(5, 6) =", m) + + print("") + print("=== Test LLVMIR with LOut ===") + out_val: t.CInt = 0 + c.LLVMIR(f"{c.LOut(out_val)} = add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) + print("LLVMIR LOut result:", out_val) + + return 0 diff --git a/Test/TestFBProject/output/067c78e9f121dce3.deps.json b/Test/TestFBProject/output/067c78e9f121dce3.deps.json index 0a11294..cadaa5e 100644 --- a/Test/TestFBProject/output/067c78e9f121dce3.deps.json +++ b/Test/TestFBProject/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestFBProject/output/29813d57621099a9.deps.json b/Test/TestFBProject/output/29813d57621099a9.deps.json index 0a11294..ae95e99 100644 --- a/Test/TestFBProject/output/29813d57621099a9.deps.json +++ b/Test/TestFBProject/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestFBProject/output/5a6a2137958c28c5.deps.json b/Test/TestFBProject/output/5a6a2137958c28c5.deps.json index 5bc5aa9..97f881b 100644 --- a/Test/TestFBProject/output/5a6a2137958c28c5.deps.json +++ b/Test/TestFBProject/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"main": "214790a9a42a868c", "stdint": "56cdd754a8a09347", "win32.win32console": "ac0664ce209738d9", "win32console": "ac0664ce209738d9"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json b/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json index 0a11294..6b67440 100644 --- a/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestFBProject/output/abf9ce3160c9279e.deps.json b/Test/TestFBProject/output/abf9ce3160c9279e.deps.json index 0a11294..fac05d5 100644 --- a/Test/TestFBProject/output/abf9ce3160c9279e.deps.json +++ b/Test/TestFBProject/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json index a1b0dcc..97f881b 100644 --- a/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestFBProject/output/fa3691e66b426950.deps.json b/Test/TestFBProject/output/fa3691e66b426950.deps.json index 0a11294..97f881b 100644 --- a/Test/TestFBProject/output/fa3691e66b426950.deps.json +++ b/Test/TestFBProject/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestFBProject/project.json b/Test/TestFBProject/project.json index a7bd9a7..431a89e 100644 --- a/Test/TestFBProject/project.json +++ b/Test/TestFBProject/project.json @@ -12,9 +12,6 @@ "linker": { "cmd": "clang++", "flags": [ - "-nostdlib", - "-nostartfiles", - "-fno-builtin", "-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lucrt", diff --git a/Test/TestFBProject/temp/067c78e9f121dce3.pyi b/Test/TestFBProject/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/TestFBProject/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/TestFBProject/temp/214790a9a42a868c.pyi b/Test/TestFBProject/temp/214790a9a42a868c.pyi deleted file mode 100644 index 4aa4f2f..0000000 --- a/Test/TestFBProject/temp/214790a9a42a868c.pyi +++ /dev/null @@ -1,33 +0,0 @@ -""" -Auto-generated Python stub file from main.py -Module: main -""" - - -from stdint import * -import win32.win32console -import t, c - -def add_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - pass - -def mul_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - pass - - -class AppError(Exception): - pass -class DiskError(AppError): - pass -class NetworkError(AppError): - pass -class TimeoutError(NetworkError): - pass - -def raise_disk() -> t.CVoid | t.State: pass - -def raise_network() -> t.CVoid | t.State: pass - -def raise_timeout() -> t.CVoid | t.State: pass - -def main() -> t.CInt | t.CExport | t.State: pass diff --git a/Test/TestFBProject/temp/29813d57621099a9.pyi b/Test/TestFBProject/temp/29813d57621099a9.pyi new file mode 100644 index 0000000..a5e9923 --- /dev/null +++ b/Test/TestFBProject/temp/29813d57621099a9.pyi @@ -0,0 +1,85 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass diff --git a/Test/TestFBProject/temp/3727eb00d15bf59d.pyi b/Test/TestFBProject/temp/3727eb00d15bf59d.pyi index 8a058f6..e778d1b 100644 --- a/Test/TestFBProject/temp/3727eb00d15bf59d.pyi +++ b/Test/TestFBProject/temp/3727eb00d15bf59d.pyi @@ -24,10 +24,10 @@ class NetworkError(AppError): class TimeoutError(NetworkError): pass -def raise_disk() -> t.CVoid | t.State: pass +def raise_disk() -> t.CInt: pass -def raise_network() -> t.CVoid | t.State: pass +def raise_network() -> t.CInt: pass -def raise_timeout() -> t.CVoid | t.State: pass +def raise_timeout() -> t.CInt: pass -def main() -> t.CInt | t.CExport | t.State: pass +def main() -> t.CInt | t.CExport: pass diff --git a/Test/TestFBProject/temp/5a6a2137958c28c5.pyi b/Test/TestFBProject/temp/5a6a2137958c28c5.pyi index 0ed80f0..a137977 100644 --- a/Test/TestFBProject/temp/5a6a2137958c28c5.pyi +++ b/Test/TestFBProject/temp/5a6a2137958c28c5.pyi @@ -1,6 +1,6 @@ """ -Auto-generated Python stub file from win32.win32base.py -Module: win32.win32base +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base """ import c diff --git a/Test/TestFBProject/temp/72e2d5ccb7cedcf1.pyi b/Test/TestFBProject/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/TestFBProject/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/TestFBProject/temp/abf9ce3160c9279e.pyi b/Test/TestFBProject/temp/abf9ce3160c9279e.pyi new file mode 100644 index 0000000..4249b58 --- /dev/null +++ b/Test/TestFBProject/temp/abf9ce3160c9279e.pyi @@ -0,0 +1,179 @@ +""" +Auto-generated Python stub file from w32.win32file.py +Module: w32.win32file +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +GENERIC_READ: t.CDefine = 0x80000000 +GENERIC_WRITE: t.CDefine = 0x40000000 +GENERIC_EXECUTE: t.CDefine = 0x20000000 +GENERIC_ALL: t.CDefine = 0x10000000 +FILE_SHARE_READ: t.CDefine = 0x00000001 +FILE_SHARE_WRITE: t.CDefine = 0x00000002 +FILE_SHARE_DELETE: t.CDefine = 0x00000004 +CREATE_NEW: t.CDefine = 1 +CREATE_ALWAYS: t.CDefine = 2 +OPEN_EXISTING: t.CDefine = 3 +OPEN_ALWAYS: t.CDefine = 4 +TRUNCATE_EXISTING: t.CDefine = 5 +FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001 +FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002 +FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020 +FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100 +FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800 +FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000 +FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000 +FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000 +FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000 +FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000 +FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000 +FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000 +FILE_BEGIN: t.CDefine = 0 +FILE_CURRENT: t.CDefine = 1 +FILE_END: t.CDefine = 2 +STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10) +STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11) +STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12) +MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001 +MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002 +MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008 + +class BY_HANDLE_FILE_INFORMATION: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + dwVolumeSerialNumber: ULONG + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + nNumberOfLinks: ULONG + nFileIndexHigh: ULONG + nFileIndexLow: ULONG +class WIN32_FIND_DATAA: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: CHARPTR + cAlternateFileName: CHARPTR +class WIN32_FIND_DATAW: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: WCHARPTR + cAlternateFileName: WCHARPTR + +def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass + +def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass + +def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass + +def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass + +def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass + +def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass + +def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass + +def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass + +def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass + +def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass + +def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass + +def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass + +def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass + +def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass + +def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass + +def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass + +def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass + +def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass + +def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass + +def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass + +def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass + +def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass diff --git a/Test/TestFBProject/temp/ac0664ce209738d9.pyi b/Test/TestFBProject/temp/ac0664ce209738d9.pyi deleted file mode 100644 index 489db56..0000000 --- a/Test/TestFBProject/temp/ac0664ce209738d9.pyi +++ /dev/null @@ -1,138 +0,0 @@ -""" -Auto-generated Python stub file from win32.win32console.py -Module: win32.win32console -""" - -import c - - -import t -from stdint import * -from win32.win32base import * - -ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 -ENABLE_LINE_INPUT: t.CDefine = 0x0002 -ENABLE_ECHO_INPUT: t.CDefine = 0x0004 -ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 -ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 -ENABLE_INSERT_MODE: t.CDefine = 0x0020 -ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 -ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 -ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 -ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 -ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 -DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 -ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 -FOREGROUND_BLUE: t.CDefine = 0x0001 -FOREGROUND_GREEN: t.CDefine = 0x0002 -FOREGROUND_RED: t.CDefine = 0x0004 -FOREGROUND_INTENSITY: t.CDefine = 0x0008 -BACKGROUND_BLUE: t.CDefine = 0x0010 -BACKGROUND_GREEN: t.CDefine = 0x0020 -BACKGROUND_RED: t.CDefine = 0x0040 -BACKGROUND_INTENSITY: t.CDefine = 0x0080 -KEY_EVENT: t.CDefine = 0x0001 -MOUSE_EVENT: t.CDefine = 0x0002 -WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 -MENU_EVENT: t.CDefine = 0x0008 -FOCUS_EVENT: t.CDefine = 0x0010 - -class COORD: - X: SHORT - Y: SHORT -class SMALL_RECT: - Left: SHORT - Top: SHORT - Right: SHORT - Bottom: SHORT -class CONSOLE_SCREEN_BUFFER_INFO: - dwSize: COORD - dwCursorPosition: COORD - wAttributes: WORD - srWindow: SMALL_RECT - dwMaximumWindowSize: COORD -class CONSOLE_CURSOR_INFO: - dwSize: ULONG - bVisible: BOOL -class CHAR_INFO: - UnicodeChar: WCHAR - Attributes: WORD -class KEY_EVENT_RECORD: - bKeyDown: BOOL - wRepeatCount: WORD - wVirtualKeyCode: WORD - wVirtualScanCode: WORD - uChar: WCHAR - dwControlKeyState: ULONG -class MOUSE_EVENT_RECORD: - dwMousePosition: COORD - dwButtonState: ULONG - dwControlKeyState: ULONG - dwEventFlags: ULONG -class WINDOW_BUFFER_SIZE_RECORD: - dwSize: COORD -class INPUT_RECORD: - EventType: WORD - Event: KEY_EVENT_RECORD - -def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass - -def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass - -def GetConsoleCP() -> UINT | t.State: pass - -def GetConsoleOutputCP() -> UINT | t.State: pass - -def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass - -def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass - -def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass - -def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass - -def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass - -def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass - -def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass - -def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass - -def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass - -def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass - -def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass - -def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass - -def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass - -def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass - -def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass - -def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass - -def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass - -def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass - -def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass - -def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass - -def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass - -def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass - -def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass - -def AllocConsole() -> BOOL | t.State: pass - -def FreeConsole() -> BOOL | t.State: pass - -def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass - -def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/TestFBProject/temp/fa3691e66b426950.pyi b/Test/TestFBProject/temp/fa3691e66b426950.pyi new file mode 100644 index 0000000..48fd36c --- /dev/null +++ b/Test/TestFBProject/temp/fa3691e66b426950.pyi @@ -0,0 +1,80 @@ +""" +Auto-generated Python stub file from w32.fileio.py +Module: w32.fileio +""" + + +import t, c +from stdint import * +import w32.win32base +import w32.win32file + +class MODE(t.CEnum): + R = 0 + W = 1 + A = 2 + RP = 3 + WP = 4 + AP = 5 + X = 6 + XP = 7 +class FRESULT(t.CEnum): + OK = 0 + ERR = -1 + ERR_CLOSED = -2 + ERR_PERM = -3 + ERR_IO = -4 + ERR_NOTFOUND = -5 + +SEEK_SET: t.CDefine = 0 +SEEK_CUR: t.CDefine = 1 +SEEK_END: t.CDefine = 2 +INVALID_SET_FILE_POINTER: t.CDefine = -1 +SHARE_READ: t.CDefine = 0x00000001 +SHARE_WRITE: t.CDefine = 0x00000002 +SHARE_DELETE: t.CDefine = 0x00000004 + +class File: + handle: w32.win32base.HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: File) -> 'File' | t.CPtr: pass + def __exit__(self: File) -> t.CInt: pass + def read(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: File, s: str) -> LONG: pass + def seek(self: File, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: File) -> LONG: pass + def close(self: File) -> LONG: pass + def flush(self: File) -> LONG: pass + def size(self: File) -> LONGLONG: pass + def readline(self: File, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: File, buf: bytes, max_count: ULONG) -> LONG: pass +class FileW: + handle: HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass + def __exit__(self: FileW) -> t.CInt: pass + def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: FileW, s: str) -> LONG: pass + def seek(self: FileW, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: FileW) -> LONG: pass + def close(self: FileW) -> LONG: pass + def flush(self: FileW) -> LONG: pass + def size(self: FileW) -> LONGLONG: pass + def readline(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + +def open(filename: str, mode: ULONG, share: ULONG) -> File | t.CPtr: pass + +def openw(filename: LPCWSTR, mode: ULONG, share: ULONG) -> FileW | t.CPtr: pass diff --git a/Test/TestProject/App/__zlib/__init__.py b/Test/TestProject/App/__zlib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/Test/TestProject/App/__zlib/pyzlib.py b/Test/TestProject/App/__zlib/pyzlib.py deleted file mode 100644 index 78bc227..0000000 --- a/Test/TestProject/App/__zlib/pyzlib.py +++ /dev/null @@ -1,550 +0,0 @@ -from stdint import * -import zdeflate -import zinflate -import zchecksum -import zdef -import zhuff -import stdlib -import string -import stdio -import t, c - - -# ============================================================ -# Constants - matching Python zlib module names and values -# ============================================================ - -# Compression levels -Z_NO_COMPRESSION: t.CDefine = 0 -Z_BEST_SPEED: t.CDefine = 1 -Z_BEST_COMPRESSION: t.CDefine = 9 -Z_DEFAULT_COMPRESSION: t.CDefine = (-1) - -# Compression methods -DEFLATED: t.CDefine = 8 - -# Flush modes -Z_NO_FLUSH: t.CDefine = 0 -Z_PARTIAL_FLUSH: t.CDefine = 1 -Z_SYNC_FLUSH: t.CDefine = 2 -Z_FULL_FLUSH: t.CDefine = 3 -Z_FINISH: t.CDefine = 4 -Z_BLOCK: t.CDefine = 5 -Z_TREES: t.CDefine = 6 - -# Strategies -Z_DEFAULT_STRATEGY: t.CDefine = 0 -Z_FILTERED: t.CDefine = 1 -Z_HUFFMAN_ONLY: t.CDefine = 2 -Z_RLE: t.CDefine = 3 -Z_FIXED: t.CDefine = 4 - -# Return codes -Z_OK: t.CDefine = 0 -Z_STREAM_END: t.CDefine = 1 -Z_NEED_DICT: t.CDefine = 2 -Z_ERRNO: t.CDefine = (-1) -Z_STREAM_ERROR: t.CDefine = (-2) -Z_DATA_ERROR: t.CDefine = (-3) -Z_MEM_ERROR: t.CDefine = (-4) -Z_BUF_ERROR: t.CDefine = (-5) -Z_VERSION_ERROR: t.CDefine = (-6) - -# Window / Buffer constants -MAX_WBITS: t.CDefine = 15 -DEF_BUF_SIZE: t.CDefine = 16384 -DEF_MEM_LEVEL: t.CDefine = 8 - -# Version -ZLIB_VERSION: t.CDefine = "1.3.2" - -pyzlib_error_msg: list[t.CChar, 512] = "" -pyzlib_error_code_val: t.CInt = 0 - -# ============================================================ -# Structures -# ============================================================ -@t.Object -class Compress: - stream: VOIDPTR - is_initialized: t.CInt - is_finished: t.CInt - level: t.CInt - method: t.CInt - wbits: t.CInt - memLevel: t.CInt - strategy: t.CInt - zdict: BYTEPTR - zdict_len: t.CSizeT - last_pos: t.CSizeT - input_buf: BYTEPTR - input_buf_len: t.CSizeT - input_buf_cap: t.CSizeT - header_written: t.CInt - - def compress(self, - data: BYTEPTR, data_len: t.CSizeT, - out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - if self.is_finished: - set_error(Z_STREAM_ERROR, "compress object already finished") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - if data_len == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - while self.input_buf_len + data_len > self.input_buf_cap: - self.input_buf_cap *= 2 - new_buf: BYTEPTR = BYTEPTR(realloc(self.input_buf, self.input_buf_cap)) - if not new_buf: - set_error(Z_MEM_ERROR, "out of memory") - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - self.input_buf = new_buf - memcpy(self.input_buf + self.input_buf_len, data, data_len) - self.input_buf_len += data_len - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def flush(self, mode: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - if mode == Z_FINISH: - if not self.header_written: - self.header_written = 1 - input_data: BYTEPTR = self.input_buf - input_len: t.CSizeT = self.input_buf_len - if input_len == 0: - s.writer.write_bits(1, 1) - s.writer.write_bits(1, 2) - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - lit_tree.encode_symbol(256, c.Addr(s.writer)) - else: - s.adler = zchecksum.zchecksum_adler32(input_data, input_len, 1) - s.compress_block(input_data, input_len, 1) - s.is_finished = 1 - if s.wbits >= 0: - s.writer.align() - adler: t.CUInt32T = s.adler - s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF - s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF - s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF - s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF - s.writer.byte_pos += 4 - self.is_finished = 1 - total: t.CSizeT = s.writer.total() - result: BYTEPTR = BYTEPTR(malloc(total)) - if result: memcpy(result, s.writer.buf, total) - c.Set(c.Deref(out_len), total) - free(self.input_buf) - self.input_buf = None - self.input_buf_len = 0 - self.input_buf_cap = 0 - return result - elif mode == Z_SYNC_FLUSH or mode == Z_FULL_FLUSH: - input_data: BYTEPTR = self.input_buf - input_len: t.CSizeT = self.input_buf_len - if input_len > 0: - s.adler = zchecksum.zchecksum_adler32(input_data, input_len, s.adler) - s.compress_block(input_data, input_len, 0) - self.input_buf_len = 0 - s.writer.write_bits(0, 1) - s.writer.write_bits(0, 2) - s.writer.align() - prev_pos: t.CSizeT = self.last_pos - total: t.CSizeT = s.writer.total() - delta: t.CSizeT = total - prev_pos - self.last_pos = s.writer.byte_pos - if delta == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - result: BYTEPTR = BYTEPTR(malloc(delta)) - if result: memcpy(result, s.writer.buf + prev_pos, delta) - c.Set(c.Deref(out_len), delta) - return result - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def copy(self) -> Compress | t.CPtr: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - copy_obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__()) - if not copy_obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - copy_obj.stream = s.copy() - if not copy_obj.stream: - free(copy_obj) - set_error(Z_MEM_ERROR, "out of memory") - return None - copy_obj.is_initialized = 1 - copy_obj.is_finished = self.is_finished - copy_obj.level = self.level - copy_obj.method = self.method - copy_obj.wbits = self.wbits - copy_obj.memLevel = self.memLevel - copy_obj.strategy = self.strategy - copy_obj.last_pos = self.last_pos - copy_obj.header_written = self.header_written - if self.input_buf and self.input_buf_len > 0: - copy_obj.input_buf = BYTEPTR(calloc(1, self.input_buf_cap)) - if copy_obj.input_buf: - memcpy(copy_obj.input_buf, self.input_buf, self.input_buf_len) - copy_obj.input_buf_cap = self.input_buf_cap - copy_obj.input_buf_len = self.input_buf_len - else: - copy_obj.input_buf = BYTEPTR(calloc(1, 256)) - copy_obj.input_buf_cap = 256 - copy_obj.input_buf_len = 0 - if self.zdict and self.zdict_len > 0: - copy_obj.zdict = clone_bytes(self.zdict, self.zdict_len) - copy_obj.zdict_len = self.zdict_len - return copy_obj - - def delete(self): - if self.is_initialized and self.stream: - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - s.destroy() - free(self.zdict) - free(self.input_buf) - free(self) - - def __del__(self): - self.delete() - - -@t.Object -class Decompress: - stream: VOIDPTR - is_initialized: t.CInt - eof: t.CInt - wbits: t.CInt - zdict: BYTEPTR - zdict_len: t.CSizeT - _unused_data: BYTEPTR - _unused_data_len: t.CSizeT - _unused_data_cap: t.CSizeT - _unconsumed_tail: BYTEPTR - _unconsumed_tail_len: t.CSizeT - _unconsumed_tail_cap: t.CSizeT - input_buf: BYTEPTR - input_buf_len: t.CSizeT - input_buf_cap: t.CSizeT - - def decompress(self, data: BYTEPTR, data_len: t.CSizeT, - max_length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - if self.eof: - if data and data_len > 0: - append_bytes(c.Addr(self._unused_data), c.Addr(self._unused_data_len), - c.Addr(self._unused_data_cap), data, data_len) - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - self._unconsumed_tail_len = 0 - if data and data_len > 0: - append_bytes(c.Addr(self.input_buf), c.Addr(self.input_buf_len), - c.Addr(self.input_buf_cap), data, data_len) - if self.input_buf_len == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - s: zinflate.zinflate_stream | t.CPtr = zinflate.zinflate_create(self.wbits) - if not s: - set_error(Z_MEM_ERROR, "out of memory") - return None - if self.zdict and self.zdict_len > 0: - s.set_dictionary(self.zdict, self.zdict_len) - out: t.CUInt8T | t.CPtr = None - err: t.CInt = s.decompress(self.input_buf, self.input_buf_len, - max_length, c.Addr(out), out_len) - if err != 0: - s.destroy() - set_error(Z_DATA_ERROR, "decompression failed") - return None - if s.is_finished: - self.eof = 1 - if s.input_pos < s.input_len: - append_bytes(c.Addr(self._unused_data), c.Addr(self._unused_data_len), - c.Addr(self._unused_data_cap), - s.input_data + s.input_pos, - s.input_len - s.input_pos) - self.input_buf_len = 0 - else: - consumed: t.CSizeT = s.input_pos - if consumed < self.input_buf_len: - remaining: t.CSizeT = self.input_buf_len - consumed - memmove(self.input_buf, self.input_buf + consumed, remaining) - self.input_buf_len = remaining - else: - self.input_buf_len = 0 - s.destroy() - return out - - def flush(self, length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def copy(self) -> Decompress | t.CPtr: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - copy_obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__()) - if not copy_obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - copy_obj.is_initialized = 1 - copy_obj.eof = self.eof - copy_obj.wbits = self.wbits - if self.zdict and self.zdict_len > 0: - copy_obj.zdict = clone_bytes(self.zdict, self.zdict_len) - copy_obj.zdict_len = self.zdict_len - if self._unused_data and self._unused_data_len > 0: - copy_obj._unused_data = clone_bytes(self._unused_data, self._unused_data_len) - copy_obj._unused_data_len = self._unused_data_len - copy_obj._unused_data_cap = self._unused_data_len - if self._unconsumed_tail and self._unconsumed_tail_len > 0: - copy_obj._unconsumed_tail = clone_bytes(self._unconsumed_tail, self._unconsumed_tail_len) - copy_obj._unconsumed_tail_len = self._unconsumed_tail_len - copy_obj._unconsumed_tail_cap = self._unconsumed_tail_len - if self.input_buf and self.input_buf_len > 0: - copy_obj.input_buf = clone_bytes(self.input_buf, self.input_buf_len) - copy_obj.input_buf_len = self.input_buf_len - copy_obj.input_buf_cap = self.input_buf_cap - else: - copy_obj.input_buf = BYTEPTR(calloc(1, 256)) - copy_obj.input_buf_cap = 256 - copy_obj.input_buf_len = 0 - return copy_obj - - def delete(self): - free(self.zdict) - free(self._unused_data) - free(self._unconsumed_tail) - free(self.input_buf) - free(self) - - def unused_data(self, length: t.CSizeT | t.CPtr) -> BYTEPTR: - #if not self: - # if length: - # c.Set(c.Deref(length), 0) - # return None - if length: - c.Set(c.Deref(length), self._unused_data_len) - return self._unused_data - - def unconsumed_tail(self, length: t.CSizeT | t.CPtr) -> BYTEPTR: - #if not self: - # if length: - # c.Set(c.Deref(length), 0) - # return None - if length: - c.Set(c.Deref(length), self._unconsumed_tail_len) - return self._unconsumed_tail - -# def eof(self) -> t.CInt: -# # if not obj: return 0 -# return self.eof - - - -def set_error(code: int, msg: str): - global pyzlib_error_code_val, pyzlib_error_msg - pyzlib_error_code_val = code - if msg: - strncpy(pyzlib_error_msg, msg, pyzlib_error_msg.__sizeof__() - 1) - pyzlib_error_msg[pyzlib_error_msg.__sizeof__() - 1] = '\0' - else: - pyzlib_error_msg[0] = '\0' - -def clone_bytes(src: BYTEPTR, length: t.CSizeT) -> BYTEPTR: - if not src or length == 0: return None - dst: BYTEPTR = BYTEPTR(malloc(length)) - if dst: memcpy(dst, src, length) - return dst - -def append_bytes(buf: BYTE | t.CPtr[t.CPtr], length: t.CSizeT | t.CPtr, cap: t.CSizeT | t.CPtr, - data: BYTEPTR, data_len: t.CSizeT) -> t.CInt: - if not data or data_len == 0: return 0 - needed: t.CSizeT = c.Deref(length) + data_len - if needed > c.Deref(cap): - new_cap: t.CSizeT = c.Deref(cap) * 2 - if new_cap < needed: new_cap = needed - new_buf: BYTEPTR = BYTEPTR(realloc(c.Deref(buf), new_cap)) - if not new_buf: return -1 - c.Set(c.Deref(buf), new_buf) - c.Set(c.Deref(cap), new_cap) - memcpy(c.Deref(buf) + c.Deref(length), data, data_len) - c.Set(c.Deref(length), c.Deref(length) + data_len) - return 0 - - -def shrink_to_fit(buf: BYTEPTR, length: t.CSizeT) -> BYTEPTR: - if length == 0: - free(buf) - return BYTEPTR(calloc(1, 1)) - result: BYTEPTR = BYTEPTR(realloc(buf, length)) - return result if result else buf - - -def runtime_version() -> str: - return ZLIB_VERSION - -def get_error() -> str: - return pyzlib_error_msg - -def get_error_code() -> t.CInt: - return pyzlib_error_code_val - -def clear_error(): - global pyzlib_error_msg, pyzlib_error_code_val - pyzlib_error_msg[0] = '\0' - pyzlib_error_code_val = 0 - -def compress(data: BYTEPTR, data_len: t.CSizeT, - level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not data and data_len > 0: - set_error(Z_STREAM_ERROR, "data is None but data_len > 0") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: - actual_wbits = -MAX_WBITS - raw_result: UINT8PTR = zdeflate.zdeflate_one_shot(data, data_len, level, actual_wbits, out_len) - if not raw_result: - set_error(Z_DATA_ERROR, "compression failed") - return None - if wbits > MAX_WBITS: - gzip_len: t.CSizeT = 10 + c.Deref(out_len) + 8 - gzip_buf: BYTEPTR = BYTEPTR(malloc(gzip_len)) - if not gzip_buf: - free(raw_result) - set_error(Z_MEM_ERROR, "out of memory") - return None - pos: t.CSizeT = 0 - gzip_buf[pos + 0] = 0x1F - gzip_buf[pos + 1] = 0x8B - gzip_buf[pos + 2] = 0x08 - gzip_buf[pos + 3] = 0x00 - gzip_buf[pos + 4] = 0x00 - gzip_buf[pos + 5] = 0x00 - gzip_buf[pos + 6] = 0x00 - gzip_buf[pos + 7] = 0x00 - gzip_buf[pos + 8] = 0x00 - gzip_buf[pos + 9] = 0xFF - pos += 10 - - memcpy(gzip_buf + pos, raw_result, c.Deref(out_len)) - pos += c.Deref(out_len) - free(raw_result) - - crc: t.CUInt32T = zchecksum.zchecksum_crc32(data, data_len, 0) - gzip_buf[pos + 0] = (crc) & 0xFF - gzip_buf[pos + 1] = (crc >> 8) & 0xFF - gzip_buf[pos + 2] = (crc >> 16) & 0xFF - gzip_buf[pos + 3] = (crc >> 24) & 0xFF - gzip_buf[pos + 4] = (data_len) & 0xFF - gzip_buf[pos + 5] = (data_len >> 8) & 0xFF - gzip_buf[pos + 6] = (data_len >> 16) & 0xFF - gzip_buf[pos + 7] = (data_len >> 24) & 0xFF - pos += 8 - c.Set(c.Deref(out_len), pos) - return shrink_to_fit(gzip_buf, pos) - return shrink_to_fit(raw_result, c.Deref(out_len)) - - -def decompress(data: BYTEPTR, data_len: t.CSizeT, - wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not data and data_len > 0: - set_error(Z_STREAM_ERROR, "data is None but data_len > 0") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - result: UINT8PTR = zinflate.zinflate_one_shot(data, data_len, wbits, bufsize, out_len) - if not result: - set_error(Z_DATA_ERROR, "decompression failed") - return None - return shrink_to_fit(result, c.Deref(out_len)) - -def compressobj(level: t.CInt, method: t.CInt, wbits: t.CInt, - memLevel: t.CInt, strategy: t.CInt, - zdict: BYTEPTR, zdict_len: t.CSizeT) -> Compress | t.CPtr: - obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__()) - if not obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: actual_wbits = wbits - 16 - s: zdeflate.zdeflate_stream | t.CPtr = zdeflate.zdeflate_create(level, actual_wbits, memLevel, strategy) - if not s: - free(obj) - set_error(Z_MEM_ERROR, "out of memory") - return None - obj.stream = s - obj.is_initialized = 1 - obj.level = level - obj.method = method - obj.wbits = wbits - obj.memLevel = memLevel - obj.strategy = strategy - obj.input_buf = BYTEPTR(calloc(1, 256)) - obj.input_buf_cap = 256 - obj.input_buf_len = 0 - obj.header_written = 0 - if zdict and zdict_len > 0: - s.set_dictionary(zdict, zdict_len) - obj.zdict = clone_bytes(zdict, zdict_len) - obj.zdict_len = zdict_len - return obj - - -def decompressobj(wbits: t.CInt, zdict: BYTEPTR, zdict_len: t.CSizeT) -> Decompress | t.CPtr: - obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__()) - if not obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: actual_wbits = wbits - 16 - obj.stream = None - obj.is_initialized = 1 - obj.wbits = actual_wbits - if zdict and zdict_len > 0: - obj.zdict = clone_bytes(zdict, zdict_len) - obj.zdict_len = zdict_len - obj.input_buf = BYTEPTR(calloc(1, 256)) - obj.input_buf_cap = 256 - obj.input_buf_len = 0 - return obj - -def zlib_adler32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong: - return zchecksum.zchecksum_adler32(data, length, UINT32(value)) - -def zlib_crc32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong: - return zchecksum.zchecksum_crc32(data, length, UINT32(value)) - - diff --git a/Test/TestProject/App/__zlib/test_basic.c b/Test/TestProject/App/__zlib/test_basic.c deleted file mode 100644 index efa089c..0000000 --- a/Test/TestProject/App/__zlib/test_basic.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include -#include "pyzlib.h" - -int main(void) -{ - printf("=== Basic Self-Implemented zlib Test ===\n\n"); - - printf("1. Adler-32:\n"); - unsigned long a = zlib_adler32((const unsigned char *)"Hello", 5, 1); - printf(" adler32(\"Hello\") = 0x%08lX\n", a); - - unsigned long a2 = zlib_adler32((const unsigned char *)"Hel", 3, 1); - a2 = zlib_adler32((const unsigned char *)"lo", 2, a2); - printf(" incremental = 0x%08lX %s\n", a2, a == a2 ? "MATCH" : "MISMATCH"); - - printf("\n2. CRC-32:\n"); - unsigned long c = zlib_crc32((const unsigned char *)"Hello", 5, 0); - printf(" crc32(\"Hello\") = 0x%08lX\n", c); - - unsigned long c2 = zlib_crc32((const unsigned char *)"Hel", 3, 0); - c2 = zlib_crc32((const unsigned char *)"lo", 2, c2); - printf(" incremental = 0x%08lX %s\n", c2, c == c2 ? "MATCH" : "MISMATCH"); - - printf("\n3. Compress (zlib format):\n"); - const char *input = "Hello, World!"; - size_t comp_len = 0; - unsigned char *comp = zlib_compress((const unsigned char *)input, strlen(input), - Z_DEFAULT_COMPRESSION, MAX_WBITS, &comp_len); - if (comp) { - printf(" Input: %zu bytes\n", strlen(input)); - printf(" Output: %zu bytes\n", comp_len); - printf(" Hex: "); - for (size_t i = 0; i < comp_len && i < 40; i++) printf("%02X ", comp[i]); - printf("\n"); - - printf("\n4. Decompress (zlib format):\n"); - size_t dec_len = 0; - unsigned char *dec = zlib_decompress(comp, comp_len, MAX_WBITS, DEF_BUF_SIZE, &dec_len); - if (dec) { - printf(" Output: %zu bytes\n", dec_len); - printf(" Content: \"%.*s\"\n", (int)dec_len, (char *)dec); - printf(" Match: %s\n", dec_len == strlen(input) && memcmp(dec, input, dec_len) == 0 ? "YES" : "NO"); - free(dec); - } else { - printf(" FAILED! Error: %s (code %d)\n", zlib_get_error(), zlib_get_error_code()); - } - free(comp); - } else { - printf(" FAILED! Error: %s (code %d)\n", zlib_get_error(), zlib_get_error_code()); - } - - printf("\n5. Compress (raw deflate):\n"); - comp_len = 0; - comp = zlib_compress((const unsigned char *)input, strlen(input), - Z_DEFAULT_COMPRESSION, -MAX_WBITS, &comp_len); - if (comp) { - printf(" Output: %zu bytes\n", comp_len); - printf(" Hex: "); - for (size_t i = 0; i < comp_len && i < 40; i++) printf("%02X ", comp[i]); - printf("\n"); - - size_t dec_len = 0; - unsigned char *dec = zlib_decompress(comp, comp_len, -MAX_WBITS, DEF_BUF_SIZE, &dec_len); - if (dec) { - printf(" Decompress: \"%.*s\" %s\n", (int)dec_len, (char *)dec, - dec_len == strlen(input) && memcmp(dec, input, dec_len) == 0 ? "OK" : "FAIL"); - free(dec); - } else { - printf(" Decompress FAILED! Error: %s\n", zlib_get_error()); - } - free(comp); - } else { - printf(" FAILED! Error: %s (code %d)\n", zlib_get_error(), zlib_get_error_code()); - } - - printf("\nDone.\n"); - return 0; -} diff --git a/Test/TestProject/App/__zlib/test_debug.c b/Test/TestProject/App/__zlib/test_debug.c deleted file mode 100644 index 682eb28..0000000 --- a/Test/TestProject/App/__zlib/test_debug.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include "pyzlib.h" - -int main(void) -{ - printf("=== Full Self-Implemented zlib Test ===\n\n"); - - printf("1. Adler-32:\n"); - unsigned long a = zlib_adler32((const unsigned char *)"Hello", 5, 1); - printf(" adler32(\"Hello\") = 0x%08lX\n", a); - - printf("\n2. CRC-32:\n"); - unsigned long c = zlib_crc32((const unsigned char *)"Hello", 5, 0); - printf(" crc32(\"Hello\") = 0x%08lX\n", c); - - const char *tests[] = {"Hello", "Hello, World!", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", ""}; - int levels[] = {2, 6, 0}; - - for (int t = 0; t < 4; t++) { - const char *input = tests[t]; - size_t input_len = strlen(input); - printf("\n--- Test: \"%s\" (%zu bytes) ---\n", input_len > 0 ? input : "(empty)", input_len); - - for (int li = 0; li < 3; li++) { - int level = levels[li]; - printf("\n Level %d, zlib format:\n", level); - size_t comp_len = 0; - unsigned char *comp = zlib_compress((const unsigned char *)input, input_len, - level, MAX_WBITS, &comp_len); - if (comp) { - printf(" Compressed: %zu bytes\n", comp_len); - size_t dec_len = 0; - unsigned char *dec = zlib_decompress(comp, comp_len, MAX_WBITS, DEF_BUF_SIZE, &dec_len); - if (dec) { - int match = (dec_len == input_len && memcmp(dec, input, dec_len) == 0); - printf(" Decompressed: %zu bytes, Match: %s\n", dec_len, match ? "YES" : "NO"); - if (!match) { - printf(" Expected: \"%s\"\n", input_len > 0 ? input : "(empty)"); - printf(" Got: \"%.*s\"\n", (int)dec_len, (char *)dec); - } - free(dec); - } else { - printf(" Decompress FAILED: %s (code %d)\n", zlib_get_error(), zlib_get_error_code()); - } - free(comp); - } else { - printf(" Compress FAILED: %s (code %d)\n", zlib_get_error(), zlib_get_error_code()); - } - } - } - - printf("\n3. Raw deflate:\n"); - { - const char *input = "Raw deflate test"; - size_t comp_len = 0; - unsigned char *comp = zlib_compress((const unsigned char *)input, strlen(input), - Z_DEFAULT_COMPRESSION, -MAX_WBITS, &comp_len); - if (comp) { - printf(" Compressed: %zu bytes\n", comp_len); - size_t dec_len = 0; - unsigned char *dec = zlib_decompress(comp, comp_len, -MAX_WBITS, DEF_BUF_SIZE, &dec_len); - if (dec) { - printf(" Decompressed: \"%.*s\" %s\n", (int)dec_len, (char *)dec, - dec_len == strlen(input) && memcmp(dec, input, dec_len) == 0 ? "OK" : "FAIL"); - free(dec); - } else { - printf(" Decompress FAILED: %s\n", zlib_get_error()); - } - free(comp); - } - } - - printf("\nDone.\n"); - return 0; -} diff --git a/Test/TestProject/App/__zlib/test_pyzlib.py b/Test/TestProject/App/__zlib/test_pyzlib.py deleted file mode 100644 index 62ede4f..0000000 --- a/Test/TestProject/App/__zlib/test_pyzlib.py +++ /dev/null @@ -1,880 +0,0 @@ -from stdint import * -import pyzlib -import zhuff -import zdef -from stdio import printf, strlen -import stdlib -import string -import t, c - - -test_passed: t.CInt = 0 -test_failed: t.CInt = 0 -def check(name: str, condition: t.CInt, detail: str): - global test_passed, test_failed - if condition: - test_passed += 1 - printf(" [PASS] %s\n", name) - else: - test_failed += 1 - printf(" [FAIL] %s -- %s\n", name, detail if detail else "") - -def print_hex_test(data: BYTEPTR, length: t.CSizeT, max_show: t.CSizeT): - if not data or length == 0: - printf("(empty)\n") - return - show: t.CSizeT = max_show if (length > max_show) else length - i: t.CSizeT - for i in range(show): - printf("%02X ", data[i]) - if length > max_show: - printf("... (%zu bytes total)", length) - printf("\n") - -def print_separator(): - printf(" -------------------------------------------\n") - -def section_header(title: str): - printf("\n+-- %s --+\n", title) - -def section_footer(): - printf("+--------------------------------------------+\n") - -# ============================================================ - -def test_version(): - section_header("Version Info") - - ver: str = pyzlib.ZLIB_VERSION - printf(" ZLIB_VERSION (compile-time) : %s\n", ver) - check("ZLIB_VERSION not None", ver != None, "version string is None") - check("ZLIB_VERSION not empty", strlen(ver) > 0, "version string is empty") - - runtime_ver: str = pyzlib.runtime_version() - printf(" ZLIB_RUNTIME_VERSION : %s\n", runtime_ver) - check("runtime version not None", runtime_ver != None, "runtime version is None") - check("runtime version not empty", strlen(runtime_ver) > 0, "runtime version is empty") - - section_footer() - - -def test_compress_decompress(): - section_header("compress / decompress") - - inp: str = "Hello, World! This is a test of zlib compression and decompression." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("compress returns non-None", compressed != None, "compress returned None") - check("compress output size > 0", out_length > 0, "compressed size is 0") - check("compress output produced", out_length > 0, "compressed size is 0") - - printf(" Compressed (%zu bytes): ", out_length) - print_hex_test(compressed, out_length, 32) - printf(" Compression ratio: %.1f%%\n", t.CDouble(out_length) / input_length * 100) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress returns non-None", decompressed != None, "decompress returned None") - check("decompress output size matches input", dec_length == input_length, "size mismatch") - check("decompress output matches input", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - - printf(" Decompressed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(decompressed)) - - free(compressed) - free(decompressed) - section_footer() - - -def test_compress_levels(): - section_header("Compression Levels") - - inp: str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - - c0: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_NO_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 0 compress OK", c0 != None, "level 0 returned None") - printf(" Level 0 (Z_NO_COMPRESSION): %zu bytes\n", out_length) - length0: t.CSizeT = out_length - free(c0) - - c1: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_BEST_SPEED, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 1 compress OK", c1 != None, "level 1 returned None") - printf(" Level 1 (Z_BEST_SPEED) : %zu bytes\n", out_length) - free(c1) - - c6: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level -1 compress OK", c6 != None, "default level returned None") - printf(" Level -1 (DEFAULT) : %zu bytes\n", out_length) - free(c6) - - c9: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_BEST_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 9 compress OK", c9 != None, "level 9 returned None") - printf(" Level 9 (Z_BEST_COMPRESS) : %zu bytes\n", out_length) - length9: t.CSizeT = out_length - free(c9) - - check("level 9 smaller than level 0", length9 < length0, "level 9 not smaller than level 0") - - section_footer() - - -def test_compressobj(): - section_header("compressobj (incremental)") - - part1: str = "Hello, " - part2: str = "World!" - printf(" Part 1: \"%s\"\n", part1) - printf(" Part 2: \"%s\"\n", part2) - - out_length: t.CSizeT = 0 - - s: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - check("compressobj created", s != None, "compressobj is None") - print_separator() - - c1: BYTEPTR = s.compress(BYTEPTR(part1), strlen(part1), c.Addr(out_length)) - check("compress part1 OK", c1 != None, "compress part1 failed") - printf(" Compressed part1: %zu bytes -> ", out_length) - print_hex_test(c1, out_length, 16) - total: t.CSizeT = out_length - all: BYTEPTR = None - if out_length > 0 and c1: - all = BYTEPTR(malloc(total)) - if all: memcpy(all, c1, out_length) - free(c1) - - c2: BYTEPTR = s.compress(BYTEPTR(part2), - strlen(part2), c.Addr(out_length)) - check("compress part2 OK", c2 != None, "compress part2 failed") - printf(" Compressed part2: %zu bytes -> ", out_length) - print_hex_test(c2, out_length, 16) - if out_length > 0 and c2: - new_all: BYTEPTR = BYTEPTR(realloc(all, total + out_length)) - if new_all: - all = new_all - memcpy(all + total, c2, out_length) - total += out_length - free(c2) - - c3: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush (Z_FINISH) OK", c3 != None, "flush failed") - printf(" Flush result : %zu bytes -> ", out_length) - print_hex_test(c3, out_length, 16) - if out_length > 0 and c3: - new_all: BYTEPTR = realloc(all, total + out_length) # 隐式转换 - if new_all: - all = new_all - memcpy(all + total, c3, out_length) - total += out_length - free(c3) - - print_separator() - - if all: - dec_length: t.CSizeT = 0 - dec: BYTEPTR = pyzlib.decompress(all, total, pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress incremental OK", dec != None, "decompress returned None") - check("decompress incremental size", dec != None and dec_length == strlen(part1) + strlen(part2), "size mismatch") - check("decompress incremental content", - dec != None and memcmp(dec, "Hello, World!", dec_length) == 0, "content mismatch") - if dec: - printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - free(all) - - s.delete() # del s - section_footer() - -def test_decompressobj(): - section_header("decompressobj") - - inp: str = "Test data for decompress object." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - check("decompressobj created", d != None, "decompressobj is None") - check("eof is false initially", d.eof == 0, "eof should be 0") - print_separator() - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(compressed, out_length, - 0, c.Addr(dec_length)) - check("decompress OK", dec != None, "decompress returned None") - check("decompress size", dec != None and dec_length == input_length, "size mismatch") - check("decompress content", dec != None and memcmp(dec, inp, input_length) == 0, "content mismatch") - check("eof is true after stream end", d.eof == 1, "eof should be 1") - - if dec: - printf(" Decompressed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(dec)) - printf(" eof = %d\n", d.eof) - - free(dec) - free(compressed) - d.delete() - section_footer() - -def test_decompressobj_max_lengthgth(): - section_header("decompressobj max_lengthgth") - - inp: str = "This is a longer string for testing max_lengthgth parameter in decompress." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(compressed, out_length, - 10, c.Addr(dec_length)) - check("max_lengthgth decompress OK", dec != None, "decompress returned None") - check("max_lengthgth limits output", dec_length <= 10, "output exceeded max_lengthgth") - if dec: - printf(" First chunk (max_lengthgth=10): \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - - tail_length: t.CSizeT = 0 - tail: BYTEPTR = d.unconsumed_tail(c.Addr(tail_length)) - check("unconsumed_tail exists", tail != None or tail_length == 0, "no unconsumed_tail") - printf(" unconsumed_tail: %zu bytes remaining\n", tail_length) - printf(" eof = %d\n", d.eof) - - if tail_length > 0 or not d.eof: - flushed: BYTEPTR = d.flush(pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("flush after max_lengthgth OK", flushed != None, "flush returned None") - if flushed: printf(" Flushed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(flushed)) - free(flushed) - - printf(" eof after flush = %d\n", d.eof) - - d.delete() - free(compressed) - section_footer() - - -def test_decompressobj_unused_data(): - section_header("decompressobj unused_data") - - inp: str = "Hello" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - total_length: t.CSizeT = out_length + 5 - combined: BYTEPTR = BYTEPTR(malloc(total_length)) - memcpy(combined, compressed, out_length) - memcpy(combined + out_length, "EXTRA", 5) - free(compressed) - printf(" Combined (compressed + \"EXTRA\"): %zu bytes\n", total_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(combined, total_length, - 0, c.Addr(dec_length)) - check("decompress with extra OK", dec != None, "decompress returned None") - check("eof after stream end", d.eof == 1, "eof should be 1") - if dec: - printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - - print_separator() - - unused_length: t.CSizeT = 0 - unused: BYTEPTR = d.unused_data(c.Addr(unused_length)) - check("unused_data exists", unused != None and unused_length > 0, "no unused_data") - check("unused_data is EXTRA", unused_length == 5 and unused != None and memcmp(unused, "EXTRA", 5) == 0, "unused_data mismatch") - printf(" unused_data (%zu bytes): \"%.*s\"\n", unused_length, t.CInt(unused_length), str(unused)) - - d.delete() - free(combined) - section_footer() - - -def test_compress_copy(): - section_header("Compress.copy()") - - inp: str = "Copy test data for compress object" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - c1: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - c1.compress(BYTEPTR(inp), input_length, c.Addr(out_length)) - printf(" Original: compressed %zu bytes so far\n", out_length) - - c2: pyzlib.Compress | t.CPtr = c1.copy() - check("compress copy OK", c2 != None, "copy returned None") - printf(" Copied compressobj\n") - - print_separator() - - f1: BYTEPTR = c1.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush original OK", f1 != None, "flush original failed") - length1: t.CSizeT = out_length - printf(" Original flush: %zu bytes\n", length1) - free(f1) - - f2: BYTEPTR = c2.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush copy OK", f2 != None, "flush copy failed") - length2: t.CSizeT = out_length - printf(" Copy flush : %zu bytes\n", length2) - free(f2) - - check("copy produces same output", length1 == length2, "output lengthgths differ") - - c1.delete() - c2.delete() - section_footer() - - -def test_decompress_copy(): - section_header("Decompress.copy()") - - inp: str = "Decompress copy test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d1: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - d2: pyzlib.Decompress | t.CPtr = d1.copy() - check("decompress copy OK", d2 != None, "copy returned None") - printf(" Copied decompressobj\n") - - print_separator() - - dec_length1: t.CSizeT = 0 - dec_length2: t.CSizeT = 0 - dec1: BYTEPTR = d1.decompress(compressed, out_length, - 0, c.Addr(dec_length1)) - dec2: BYTEPTR = d2.decompress(compressed, out_length, - 0, c.Addr(dec_length2)) - check("decompress copy output size", dec_length1 == dec_length2, "sizes differ") - check("decompress copy output content", - dec1 and dec2 and memcmp(dec1, dec2, dec_length1) == 0, "content differs") - - if dec1: printf(" Original: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length1), str(dec1), dec_length1) - if dec2: printf(" Copy : \"%.*s\" (%zu bytes)\n", t.CInt(dec_length2), str(dec2), dec_length2) - - free(dec1) - free(dec2) - free(compressed) - d1.delete() - d2.delete() - section_footer() - - -def test_adler32(): - section_header("adler32 checksum") - - checksum: ULONG = pyzlib.zlib_adler32(BYTEPTR("Hello"), 5, 1) - printf(" adler32(\"Hello\") = 0x%08lX (%lu)\n", checksum, checksum) - check("adler32 returns non-zero", checksum != 0, "checksum is 0") - - incremental: ULONG = pyzlib.zlib_adler32(BYTEPTR("Hel"), 3, 1) - printf(" adler32(\"Hel\") = 0x%08lX\n", incremental) - incremental = pyzlib.zlib_adler32(BYTEPTR("lo"), 2, incremental) - printf(" adler32(\"lo\", prev) = 0x%08lX\n", incremental) - check("adler32 incremental matches one-shot", incremental == checksum, "incremental != one-shot") - printf(" Incremental == One-shot: %s\n", incremental == "YES" if checksum else "NO") - - section_footer() - - -def test_crc32(): - section_header("crc32 checksum") - - checksum: ULONG = pyzlib.zlib_crc32(BYTEPTR("Hello"), 5, 0) - printf(" crc32(\"Hello\") = 0x%08lX (%lu)\n", checksum, checksum) - check("crc32 returns non-zero", checksum != 0, "checksum is 0") - - incremental: ULONG = pyzlib.zlib_crc32(BYTEPTR("Hel"), 3, 0) - printf(" crc32(\"Hel\") = 0x%08lX\n", incremental) - incremental = pyzlib.zlib_crc32(BYTEPTR("lo"), 2, incremental) - printf(" crc32(\"lo\", prev) = 0x%08lX\n", incremental) - check("crc32 incremental matches one-shot", incremental == checksum, "incremental != one-shot") - printf(" Incremental == One-shot: %s\n", incremental == "YES" if checksum else "NO") - - section_footer() - - -def test_empty_compress(): - section_header("Empty data compress/decompress") - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(""), 0, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("compress empty OK", compressed != None, "compress empty returned None") - check("compress empty output > 0", out_length > 0, "compressed empty is 0 bytes") - printf(" Empty input compressed: %zu bytes (header only)\n", out_length) - printf(" Hex: ") - print_hex_test(compressed, out_length, 32) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress empty OK", decompressed != None, "decompress empty returned None") - check("decompress empty size == 0", dec_length == 0, "decompressed size != 0") - printf(" Decompressed back: %zu bytes\n", dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_gzip_format(): - section_header("Gzip format (wbits=31)") - - inp: str = "Gzip format test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\" (%zu bytes)\n", inp, input_length) - - gzip_wbits: t.CInt = pyzlib.MAX_WBITS + 16 - printf(" wbits = MAX_WBITS + 16 = %d\n", gzip_wbits) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, gzip_wbits, c.Addr(out_length)) - check("gzip compress OK", compressed != None, "gzip compress failed") - printf(" Gzip compressed: %zu bytes\n", out_length) - printf(" Header bytes: ") - print_hex_test(compressed, 4 if (out_length > 4) else out_length, 4) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - gzip_wbits, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("gzip decompress OK", decompressed != None, "gzip decompress failed") - check("gzip decompress size", dec_length == input_length, "size mismatch") - check("gzip decompress content", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - if decompressed: printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(decompressed), dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_raw_deflate(): - section_header("Raw deflate (wbits=-15)") - - inp: str = "Raw deflate test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\" (%zu bytes)\n", inp, input_length) - - raw_wbits: t.CInt = -pyzlib.MAX_WBITS - printf(" wbits = -MAX_WBITS = %d\n", raw_wbits) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, raw_wbits, c.Addr(out_length)) - check("raw deflate compress OK", compressed != None, "raw deflate compress failed") - printf(" Raw compressed: %zu bytes\n", out_length) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - raw_wbits, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("raw deflate decompress OK", decompressed != None, "raw deflate decompress failed") - check("raw deflate decompress size", dec_length == input_length, "size mismatch") - check("raw deflate decompress content", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - if decompressed: printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(decompressed), dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_zdict(): - section_header("Preset dictionary (zdict)") - - dict: str = "common words that appear frequently in the data" - inp: str = "common words that appear frequently" - input_length: t.CSizeT = strlen(inp) - printf(" Dictionary: \"%s\" (%zu bytes)\n", dict, strlen(dict)) - printf(" Input : \"%s\" (%zu bytes)\n", inp, input_length) - - out_length: t.CSizeT = 0 - s: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, - BYTEPTR(dict), strlen(dict)) - check("compressobj with zdict OK", s != None, "compressobj with zdict failed") - - comp_data: BYTEPTR = s.compress(BYTEPTR(inp), - input_length, c.Addr(out_length)) - check("compress with zdict OK", comp_data != None, "compress with zdict failed") - printf(" Compressed with zdict: %zu bytes\n", out_length) - free(comp_data) - - flush_data: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush with zdict OK", flush_data != None, "flush with zdict failed") - printf(" Flush: %zu bytes\n", out_length) - free(flush_data) - - print_separator() - - total_comp: t.CSizeT = out_length - s.delete() - - s = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - comp_no_dict: BYTEPTR = s.compress(BYTEPTR(inp), - input_length, c.Addr(out_length)) - flush_no_dict: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - no_dict_total: t.CSizeT = 0 - if comp_no_dict: no_dict_total += out_length - if flush_no_dict: no_dict_total += out_length - printf(" Without zdict: ~%zu bytes compressed\n", no_dict_total) - printf(" With zdict : %zu bytes compressed\n", total_comp) - free(comp_no_dict) - free(flush_no_dict) - s.delete() - - section_footer() - - -def test_huffman_tree(): - section_header("Huffman tree construction") - - printf(" --- Fixed Huffman tree (literal/lengthgth) ---\n") - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - - check("fixed lit tree count == 288", lit_tree.count == 288, "count mismatch") - check("fixed lit tree max_bits == 9", lit_tree.max_bits == 9, "max_bits mismatch") - - has_8bit: t.CInt = 0 - has_9bit: t.CInt = 0 - has_7bit: t.CInt = 0 - for i in range(143 + 1): - if lit_tree.codes[i].bits == 8: - has_8bit += 1 - for i in range(143 + 1, 255 + 1): - if lit_tree.codes[i].bits == 9: - has_9bit += 1 - for i in range(255 + 1, 279 + 1): - if lit_tree.codes[i].bits == 7: - has_7bit += 1 - check("0-143 are 8-bit", has_8bit == 144, "wrong count") - check("144-255 are 9-bit", has_9bit == 112, "wrong count") - check("256-279 are 7-bit", has_7bit == 24, "wrong count") - - printf(" 0-143: %d codes with 8 bits\n", has_8bit) - printf(" 144-255: %d codes with 9 bits\n", has_9bit) - printf(" 256-279: %d codes with 7 bits\n", has_7bit) - printf(" 280-287: 8-bit (end-of-block 256 = 7-bit)\n") - printf(" EOB (256): code=0x%X, bits=%d\n", lit_tree.codes[256].code, lit_tree.codes[256].bits) - - printf("\n --- Fixed Huffman tree (distance) ---\n") - dist_tree = zhuff.zhuff_tree() - dist_tree.build_fixed_dist_tree() - - check("fixed dist tree count == 32", dist_tree.count == 32, "count mismatch") - check("fixed dist tree max_bits == 5", dist_tree.max_bits == 5, "max_bits mismatch") - - all_5bit: t.CInt = 1 - for i in range(32): - if dist_tree.codes[i].bits != 5: - all_5bit = 0 - check("all 32 distance codes are 5-bit", all_5bit, "not all 5-bit") - printf(" All 32 distance codes: 5 bits each\n") - - printf("\n --- Dynamic Huffman tree from frequencies ---\n") - freqs: list[t.CInt, 256] - memset(freqs, 0, freqs.__sizeof__()) - freqs['A'] = 50 - freqs['B'] = 25 - freqs['C'] = 12 - freqs['D'] = 6 - freqs['E'] = 3 - freqs['F'] = 1 - freqs[256] = 1 - - dyn_tree = zhuff.zhuff_tree() - dyn_tree.build_codes(freqs, 257, 15) - - check("dynamic tree count == 257", dyn_tree.count == 257, "count mismatch") - check("dynamic tree max_bits <= 15", dyn_tree.max_bits <= 15, "max_bits overflow") - - total_codes: t.CInt = 0 - max_length_found: t.CInt = 0 - for i in range(257): - if dyn_tree.codes[i].bits > 0: - total_codes += 1 - if dyn_tree.codes[i].bits > max_length_found: - max_length_found = dyn_tree.codes[i].bits - check("dynamic tree has 7 active codes", total_codes == 7, "wrong active count") - check("dynamic tree max code lengthgth found <= 15", max_length_found <= 15, "code lengthgth overflow") - - printf(" Frequencies: A=50, B=25, C=12, D=6, E=3, F=1, EOB=1\n") - printf(" Active codes: %d, max code lengthgth: %d\n", total_codes, max_length_found) - - printf(" Code assignments:\n") - names: list[str, None] = ["A","B","C","D","E","F"] # 一个都æ˜?char* 的数ç»? - syms: list[t.CInt, None] = ['A','B','C','D','E','F'] - for i in range(6): - printf(" '%s' (freq=%3d): code=0x%04X, bits=%d\n", - names[i], freqs[syms[i]], - dyn_tree.codes[syms[i]].code, - dyn_tree.codes[syms[i]].bits) - - - - printf(" EOB (freq=1): code=0x%04X, bits=%d\n", - dyn_tree.codes[256].code, dyn_tree.codes[256].bits) - a_bits: t.CInt = dyn_tree.codes['A'].bits - f_bits: t.CInt = dyn_tree.codes['F'].bits - check("high-freq symbol has shorter code", a_bits <= f_bits, "A should be <= F") - printf(" High-freq 'A' (%d bits) <= low-freq 'F' (%d bits): %s\n", - a_bits, f_bits, "YES" if (a_bits <= f_bits) else "NO") - - printf("\n --- Huffman encode/decode roundtrip ---\n") - freqs: list[t.CInt, 288] - memset(freqs, 0, freqs.__sizeof__()) - freqs['H'] = 10 - freqs['e'] = 8 - freqs['l'] = 20 - freqs['o'] = 8 - freqs[' '] = 5 - freqs['W'] = 3 - freqs['r'] = 5 - freqs['d'] = 3 - freqs['!'] = 2 - freqs[256] = 1 - - enc_tree = zhuff.zhuff_tree() - enc_tree.build_codes(freqs, 257, 15) - - dec_tree = zhuff.zhuff_decode_tree() - dec_tree.build_decode_tree(c.Addr(enc_tree)) - - writer = zdef.zbit_writer() - - symbols: list[t.CInt, 16] - symbols[0] = 'H'; symbols[1] = 'e'; symbols[2] = 'l'; symbols[3] = 'l' - symbols[4] = 'o'; symbols[5] = ' '; symbols[6] = 'W'; symbols[7] = 'o' - symbols[8] = 'r'; symbols[9] = 'l'; symbols[10] = 'd'; symbols[11] = '!' - symbols[12] = 256 - num_symbols: t.CInt = 13 - - for i in range(num_symbols): - enc_tree.encode_symbol(symbols[i], c.Addr(writer)) - - reader = zdef.zbit_reader() - reader.buf = writer.buf - reader.length = writer.byte_pos + (1 if (writer.bit_pos > 0) else 0) - reader.byte_pos = 0 - reader.bit_pos = 0 - - roundtrip_ok: t.CInt = 1 - for i in range(num_symbols): - decoded: t.CInt = dec_tree.decode_symbol(c.Addr(reader)) - if decoded != symbols[i]: - roundtrip_ok = 0 - printf(" MISMATCH at symbol %d: expected %d, got %d\n", i, symbols[i], decoded) - break - check("encode/decode roundtrip matches", roundtrip_ok, "roundtrip failed") - printf(" Encoded %d symbols into %zu bytes, decoded all correctly\n", - num_symbols, writer.byte_pos + (1 if (writer.bit_pos > 0) else 0)) - - free(writer.buf) - - printf("\n --- Overflow handling (many symbols, limited max_bits) ---\n") - freqs: list[t.CInt, 256] - for i in range(256): - freqs[i] = 1 - freqs[256] = 1 - - tree = zhuff.zhuff_tree() - tree.build_codes(freqs, 257, 15) - - overflow_ok: t.CInt = 1 - for i in range(257): - if tree.codes[i].bits > 15 or tree.codes[i].bits < 0: - overflow_ok = 0 - break - check("all code lengthgths <= 15 with 257 symbols", overflow_ok, "code lengthgth overflow") - - bl_count: list[t.CInt, 16] = [0] - for i in range(257): - if tree.codes[i].bits > 0: - bl_count[tree.codes[i].bits] += 1 - printf(" Code lengthgth distribution (257 equal-freq symbols, max_bits=15):\n") - for i in range(1, 15 + 1): - if bl_count[i] > 0: - printf(" %2d bits: %3d codes\n", i, bl_count[i]) - - dt = zhuff.zhuff_decode_tree() - dt.build_decode_tree(c.Addr(tree)) - - w = zdef.zbit_writer() - tree.encode_symbol(0, c.Addr(w)) - tree.encode_symbol(128, c.Addr(w)) - tree.encode_symbol(255, c.Addr(w)) - tree.encode_symbol(256, c.Addr(w)) - - r = zdef.zbit_reader() - r.buf = w.buf - r.length = w.byte_pos + (1 if (w.bit_pos > 0) else 0) - r.byte_pos = 0 - r.bit_pos = 0 - - s0: t.CInt = dt.decode_symbol(c.Addr(r)) - s1: t.CInt = dt.decode_symbol(c.Addr(r)) - s2: t.CInt = dt.decode_symbol(c.Addr(r)) - s3: t.CInt = dt.decode_symbol(c.Addr(r)) - - check("overflow roundtrip: symbol 0", s0 == 0, "decode mismatch") - check("overflow roundtrip: symbol 128", s1 == 128, "decode mismatch") - check("overflow roundtrip: symbol 255", s2 == 255, "decode mismatch") - check("overflow roundtrip: symbol 256 (EOB)", s3 == 256, "decode mismatch") - - free(w.buf) - - - printf("\n --- Kraft inequality check ---\n") - freqs: list[t.CInt, 256] - memset(freqs, 0, freqs.__sizeof__()) - freqs['X'] = 100 - freqs['Y'] = 50 - freqs['Z'] = 25 - freqs[256] = 1 - - tree = zhuff.zhuff_tree() - tree.build_codes(freqs, 257, 15) - - kraft_sum: t.CDouble = 0.0 - for i in range(257): - if tree.codes[i].bits > 0: - kraft_sum += 1.0 / (t.CDouble(ULONGLONG(1) << tree.codes[i].bits)) - check("Kraft inequality: sum <= 1.0", kraft_sum <= 1.0 + 1e-9, "Kraft violated") - printf(" Kraft sum = %.10f (must be <= 1.0)\n", kraft_sum) - - section_footer() - - -def test_error_handling(): - section_header("Error handling") - - out_length: t.CSizeT = 0 - printf(" Trying to decompress garbage data...\n") - - result: BYTEPTR = pyzlib.decompress(BYTEPTR("garbage"), 7, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(out_length)) - check("decompress garbage returns None", result == None, "should have returned None") - printf(" Error code : %d\n", pyzlib.get_error_code()) - printf(" Error message: \"%s\"\n", pyzlib.get_error()) - check("error message set", strlen(pyzlib.get_error()) > 0, "error message is empty") - check("error code is set", pyzlib.get_error_code() != pyzlib.Z_OK, "error code is Z_OK") - - print_separator() - - pyzlib.clear_error() - check("clear error clears code", pyzlib.get_error_code() == 0, "error code not cleared") - printf(" After clear: code=%d, msg=\"%s\"\n", pyzlib.get_error_code(), pyzlib.get_error()) - - section_footer() - - -def test_constants(): - section_header("Constants") - printf(" Compression Levels:\n") - printf(" Z_NO_COMPRESSION = %d\n", pyzlib.Z_NO_COMPRESSION) - printf(" Z_BEST_SPEED = %d\n", pyzlib.Z_BEST_SPEED) - printf(" Z_BEST_COMPRESSION = %d\n", pyzlib.Z_BEST_COMPRESSION) - printf(" Z_DEFAULT_COMPRESSION = %d\n", pyzlib.Z_DEFAULT_COMPRESSION) - printf(" Methods:\n") - printf(" DEFLATED = %d\n", pyzlib.DEFLATED) - printf(" Flush Modes:\n") - printf(" Z_NO_FLUSH = %d\n", pyzlib.Z_NO_FLUSH) - printf(" Z_PARTIAL_FLUSH = %d\n", pyzlib.Z_PARTIAL_FLUSH) - printf(" Z_SYNC_FLUSH = %d\n", pyzlib.Z_SYNC_FLUSH) - printf(" Z_FULL_FLUSH = %d\n", pyzlib.Z_FULL_FLUSH) - printf(" Z_FINISH = %d\n", pyzlib.Z_FINISH) - printf(" Z_BLOCK = %d\n", pyzlib.Z_BLOCK) - printf(" Z_TREES = %d\n", pyzlib.Z_TREES) - printf(" Strategies:\n") - printf(" Z_DEFAULT_STRATEGY = %d\n", pyzlib.Z_DEFAULT_STRATEGY) - printf(" Z_FILTERED = %d\n", pyzlib.Z_FILTERED) - printf(" Z_HUFFMAN_ONLY = %d\n", pyzlib.Z_HUFFMAN_ONLY) - printf(" Z_RLE = %d\n", pyzlib.Z_RLE) - printf(" Z_FIXED = %d\n", pyzlib.Z_FIXED) - printf(" Return Codes:\n") - printf(" Z_OK = %d\n", pyzlib.Z_OK) - printf(" Z_STREAM_END = %d\n", pyzlib.Z_STREAM_END) - printf(" Z_NEED_DICT = %d\n", pyzlib.Z_NEED_DICT) - printf(" Z_ERRNO = %d\n", pyzlib.Z_ERRNO) - printf(" Z_STREAM_ERROR = %d\n", pyzlib.Z_STREAM_ERROR) - printf(" Z_DATA_ERROR = %d\n", pyzlib.Z_DATA_ERROR) - printf(" Z_MEM_ERROR = %d\n", pyzlib.Z_MEM_ERROR) - printf(" Z_BUF_ERROR = %d\n", pyzlib.Z_BUF_ERROR) - printf(" Z_VERSION_ERROR = %d\n", pyzlib.Z_VERSION_ERROR) - printf(" Window / Buffer:\n") - printf(" MAX_WBITS = %d\n", pyzlib.MAX_WBITS) - printf(" DEF_BUF_SIZE = %d\n", pyzlib.DEF_BUF_SIZE) - printf(" DEF_MEM_LEVEL = %d\n", pyzlib.DEF_MEM_LEVEL) - section_footer() - - -def main123456() -> t.CInt: - printf("==============================================\n") - printf(" Python zlib - C Implementation Tests\n") - printf("==============================================\n") - - test_constants() - test_version() - test_compress_decompress() - test_compress_levels() - test_compressobj() - test_decompressobj() - test_decompressobj_max_lengthgth() - test_decompressobj_unused_data() - test_compress_copy() - test_decompress_copy() - test_adler32() - test_crc32() - test_empty_compress() - test_gzip_format() - test_raw_deflate() - test_zdict() - test_huffman_tree() - test_error_handling() - - printf("\n==============================================\n") - printf(" Results: %d passed, %d failed\n", test_passed, test_failed) - printf("==============================================\n") - - return 1 if test_failed > 0 else 0 - diff --git a/Test/TestProject/App/__zlib/zchecksum.py b/Test/TestProject/App/__zlib/zchecksum.py deleted file mode 100644 index 422bd5e..0000000 --- a/Test/TestProject/App/__zlib/zchecksum.py +++ /dev/null @@ -1,90 +0,0 @@ -from stdint import * -import t, c - - -def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt32T: - a: t.CUInt32T = (init >> 0) & 0xFFFF - b: t.CUInt32T = (init >> 16) & 0xFFFF - if not data or length == 0: - return init - i: t.CSizeT - for i in range(length): - a = (a + data[i]) % 65521 - b = (b + a) % 65521 - return (b << 16) | a - -crc32_table: list[t.CUInt32T, 256] = [ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBBBD6, 0xACBCCB40, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7D49, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDede9EC5, 0x47D7897F, 0x30D0B8E9, - 0xBDDA8B1C, 0xCADD8B8A, 0x53D3903A, 0x24D4C2AC, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -] - -def zchecksum_crc32(data: UINT8PTR, length: t.CSizeT, init: t.CUInt32T) -> t.CUInt32T: - crc: t.CUInt32T = init ^ 0xFFFFFFFF - if not data or length == 0: return init - i: t.CSizeT - for i in range(length): - crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8) - return crc ^ 0xFFFFFFFF - diff --git a/Test/TestProject/App/__zlib/zdef.py b/Test/TestProject/App/__zlib/zdef.py deleted file mode 100644 index 4f1918c..0000000 --- a/Test/TestProject/App/__zlib/zdef.py +++ /dev/null @@ -1,269 +0,0 @@ -from stdint import * -import stddef -import string -import stdlib -import t, c - - -# ============================================================ -# DEFLATE / zlib constants -# ============================================================ -ZDEFLATE_WINDOW_BITS: t.CDefine = 15 -ZDEFLATE_WINDOW_SIZE: t.CDefine = (1 << ZDEFLATE_WINDOW_BITS) -ZDEFLATE_WINDOW_MASK: t.CDefine = (ZDEFLATE_WINDOW_SIZE - 1) - -ZDEFLATE_MIN_MATCH: t.CDefine = 3 -ZDEFLATE_MAX_MATCH: t.CDefine = 258 - -ZDEFLATE_HASH_BITS: t.CDefine = 15 -ZDEFLATE_HASH_SIZE: t.CDefine = (1 << ZDEFLATE_HASH_BITS) -ZDEFLATE_HASH_MASK: t.CDefine = (ZDEFLATE_HASH_SIZE - 1) - -ZDEFLATE_MAX_CODES: t.CDefine = 288 -ZDEFLATE_MAX_DIST_CODES: t.CDefine = 32 -ZDEFLATE_MAX_BITS: t.CDefine = 15 -ZDEFLATE_MAX_CODELEN_CODES: t.CDefine = 19 - -ZDEFLATE_LIT_COUNT: t.CDefine = 286 -ZDEFLATE_DIST_COUNT: t.CDefine = 30 - -ZDEFLATE_LEN_SYMBOLS_BASE: t.CDefine = 257 -ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 - -# ============================================================ -# Length / Distance extra bits tables (RFC 1951) -# ============================================================ -zdeflate_len_extra_bits: list[t.CInt, 29] = [ - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, - 2, 2, 2, 2, - 3, 3, 3, 3, - 4, 4, 4, 4, - 5, 5, 5, 5, - 0 -] - -zdeflate_len_base: list[t.CInt, 29] = [ - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 13, 15, 17, - 19, 23, 27, 31, - 35, 43, 51, 59, - 67, 83, 99, 115, - 131, 163, 195, 227, - 258 -] - -zdeflate_dist_extra_bits: list[t.CInt, 30] = [ - 0, 0, 0, 0, - 1, 1, - 2, 2, - 3, 3, - 4, 4, - 5, 5, - 6, 6, - 7, 7, - 8, 8, - 9, 9, - 10, 10, - 11, 11, - 12, 12, - 13, 13 -] - -zdeflate_dist_base: list[t.CInt, 30] = [ - 1, 2, 3, 4, - 5, 7, - 9, 13, - 17, 25, - 33, 49, - 65, 97, - 129, 193, - 257, 385, - 513, 769, - 1025, 1537, - 2049, 3073, - 4097, 6145, - 8193, 12289, - 16385, 24577 -] - -zdeflate_codelen_order: list[int, 19] = [ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 -] - -# ============================================================ -# Bit writer - writes bits LSB first into a byte buffer -# ============================================================ -@t.Object -class zbit_writer: - buf: BYTE | t.CPtr - cap: t.CSizeT - byte_pos: t.CSizeT - bit_pos: t.CInt - - def __init__(self): - self.cap = 4096 - self.buf = BYTEPTR(malloc(self.cap)) - memset(self.buf, 0, self.cap) - self.byte_pos = 0 - self.bit_pos = 0 - - def ensure(self, need: t.CSizeT): - while self.byte_pos + need + 4 >= self.cap: - new_cap: t.CSizeT = self.cap * 2 - new_buf: BYTE | t.CPtr = BYTEPTR(realloc(self.buf, new_cap)) - if not new_buf: return - memset(new_buf + self.cap, 0, new_cap - self.cap) - self.buf = new_buf - self.cap = new_cap - - def write_bits(self, value: UINT, nbits: t.CInt): - self.ensure((nbits + 7) / 8 + 1) - for i in range(nbits): - if value & (UINT(1) << i): - self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - - def write_bits_rev(self, code: UINT, nbits: t.CInt): - self.ensure((nbits + 7) / 8 + 1) - for i in range(nbits - 1, -1, -1): - if code & (UINT(1) << i): - self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - - def stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - self.write_bits(1 if final else 0, 1) - self.write_bits(0, 2) - self.align() - - pos: t.CSizeT = 0 - while pos < length: - block_length: t.CSizeT = length - pos - if block_length > 65535: - block_length = 65535 - n: t.CUInt16T = t.CUInt16T(block_length) - ncomp: t.CUInt16T = ~n - self.write_bits(n, 16) - self.write_bits(ncomp, 16) - - self.ensure(block_length) - i: t.CSizeT = 0 - for i in range(block_length): - self.buf[self.byte_pos] = data[pos + i] - self.byte_pos += 1 - pos += block_length - if pos < length: - self.write_bits(0, 1) - self.write_bits(0, 2) - self.align() - - def write_zlib_header(self, wbits: t.CInt, level: t.CInt): - cinfo: t.CInt = wbits - 8 - if cinfo < 1: cinfo = 1 - if cinfo > 7: cinfo = 7 - cmf: t.CUnsignedChar = t.CUnsignedChar((cinfo << 4) | 8) - - flevel: t.CInt = 0 - if level >= 5: flevel = 3 - elif level >= 3: flevel = 1 - - flg: t.CUnsignedChar = t.CUnsignedChar(flevel << 6) - flg |= t.CUnsignedChar(31 - (cmf * 256 + flg) % 31) - - self.buf[self.byte_pos + 0] = cmf - self.buf[self.byte_pos + 1] = flg - self.byte_pos += 2 - - - def write_gzip_header(self): - self.buf[self.byte_pos + 0] = 0x1F - self.buf[self.byte_pos + 1] = 0x8B - self.buf[self.byte_pos + 2] = 0x08 - self.buf[self.byte_pos + 3] = 0x00 - self.buf[self.byte_pos + 4] = 0x00 - self.buf[self.byte_pos + 5] = 0x00 - self.buf[self.byte_pos + 6] = 0x00 - self.buf[self.byte_pos + 7] = 0x00 - self.buf[self.byte_pos + 8] = 0x00 - self.buf[self.byte_pos + 9] = 0xFF - self.byte_pos += 10 - - def align(self): - if self.bit_pos > 0: - self.bit_pos = 0 - self.byte_pos += 1 - - def total(self) -> t.CSizeT: - return self.byte_pos + (1 if (self.bit_pos > 0) else 0) - - def free(self): - free(self.buf) - self.buf = None - self.cap = 0 - self.byte_pos = 0 - self.bit_pos = 0 - - def __del__(self): - self.free() - -# ============================================================ -# Bit reader - reads bits LSB first from a byte buffer -# ============================================================ -@t.Object -class zbit_reader: - buf: BYTE | t.CPtr - length: t.CSizeT - byte_pos: t.CSizeT - bit_pos: t.CInt - - def init(self, buf: BYTE | t.CPtr, length: t.CSizeT): - self.buf = buf - self.length = length - self.byte_pos = 0 - self.bit_pos = 0 - - def read_bits(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits): - if self.byte_pos >= self.length: return -1 - if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos): - val |= (UINT(1) << i) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - def read_bits_rev(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits - 1, 0, -1): - if self.byte_pos >= self.length: return -1 - if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos): - val |= (UINT(1) << i) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - def align(self): - if self.bit_pos > 0: - self.bit_pos = 0 - self.byte_pos += 1 - -# ============================================================ -# Memory allocation helper for bare metal -# Can be replaced with custom allocator -# ============================================================ -def zdef_alloc(n: t.CSizeT) -> VOIDPTR: - return malloc(n) -def zdef_free(p: VOIDPTR): - free(p) diff --git a/Test/TestProject/App/__zlib/zdeflate.py b/Test/TestProject/App/__zlib/zdeflate.py deleted file mode 100644 index f9c5328..0000000 --- a/Test/TestProject/App/__zlib/zdeflate.py +++ /dev/null @@ -1,431 +0,0 @@ -from stdint import * -import zchecksum -import zhuff -import zdef -import string -import stdio -import t, c - - -@t.Object -class zdeflate_stream: - writer: zdef.zbit_writer - window: BYTE | t.CPtr - window_pos: t.CInt - window_size: t.CInt - hash_head: t.CInt | t.CPtr - hash_prev: t.CInt | t.CPtr - level: t.CInt - strategy: t.CInt - wbits: t.CInt - is_finished: t.CInt - adler: t.CUInt32T - - def find_match(self, data: BYTE | t.CPtr, data_len: t.CSizeT, - pos: t.CSizeT, best_dist: t.CInt | t.CPtr) -> t.CInt: - if pos + 2 >= data_len: return 0 - h: t.CUnsignedInt = zdeflate_hash(data + pos) - chain: t.CInt = self.hash_head[h] - best_len: t.CInt = zdef.ZDEFLATE_MIN_MATCH - 1 - c.Set(c.Deref(best_dist), 0) - max_chain: t.CInt = 128 if (self.level >= 5) else (32 if (self.level >= 2) else 4) - limit: t.CInt = (1 << self.wbits) if (self.wbits > 0) else zdef.ZDEFLATE_WINDOW_SIZE - if limit > zdef.ZDEFLATE_WINDOW_SIZE: - limit = zdef.ZDEFLATE_WINDOW_SIZE - attempts: t.CInt = 0 - while chain >= 0 and attempts < max_chain: - dist: t.CInt = t.CInt(pos) - chain - if dist <= 0 or dist > limit: break - match_len: t.CInt = 0 - max_len: t.CInt = t.CInt(data_len - pos) - if max_len > zdef.ZDEFLATE_MAX_MATCH: - max_len = zdef.ZDEFLATE_MAX_MATCH - while match_len < max_len and data[pos + match_len] == data[chain + match_len]: - match_len += 1 - if match_len > best_len: - best_len = match_len - c.Set(c.Deref(best_dist), dist) - if best_len >= zdef.ZDEFLATE_MAX_MATCH: break - chain = self.hash_prev[chain & zdef.ZDEFLATE_WINDOW_MASK] - if chain <= t.CInt(pos) - limit: break - attempts += 1 - return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0 - - def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT): - if pos + 2 < pos: return - h: t.CUnsignedInt = zdeflate_hash(data + pos) - self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h] - self.hash_head[h] = t.CInt(pos) - - def write_fixed_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - dist_tree.build_fixed_dist_tree() - self.writer.write_bits(1 if final else 0, 1) - self.writer.write_bits(1, 2) - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if self.level > 0 and pos + 2 < length: - match_len = self.find_match(data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_tree.encode_symbol(len_sym, c.Addr(self.writer)) - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257] - if extra > 0: - self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra) - dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist) - dist_tree.encode_symbol(dist_sym, c.Addr(self.writer)) - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra) - for i in range(match_len): - self.update_hash(data, pos + i) - pos += match_len - else: - lit_tree.encode_symbol(data[pos], c.Addr(self.writer)) - self.update_hash(data, pos) - pos += 1 - lit_tree.encode_symbol(256, c.Addr(self.writer)) - - def encode_block_data(self, data: UINT8PTR, length: t.CSizeT, - lit_tree: zhuff.zhuff_tree | t.CPtr, dist_tree: zhuff.zhuff_tree | t.CPtr): - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if self.level > 0 and pos + 2 < length: - match_len = self.find_match(data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_tree.encode_symbol(len_sym, c.Addr(self.writer)) - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257] - if extra > 0: - self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra) - dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist) - dist_tree.encode_symbol(dist_sym, c.Addr(self.writer)) - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra) - for j in range(match_len): - self.update_hash(data, pos + j) - pos += match_len - else: - lit_tree.encode_symbol(data[pos], c.Addr(self.writer)) - self.update_hash(data, pos) - pos += 1 - lit_tree.encode_symbol(256, c.Addr(self.writer)) - - - def write_dynamic_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_freqs: list[t.CInt, 288] - dist_freqs: list[t.CInt, 32] - zdeflate_count_freqs(lit_freqs, dist_freqs, self, data, length) - hlit: t.CInt = 286 - while hlit > 257 and lit_freqs[hlit - 1] == 0: hlit -= 1 - hdist: t.CInt = 30 - while hdist > 1 and dist_freqs[hdist - 1] == 0: hdist -= 1 - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_codes(lit_freqs, hlit, zdef.ZDEFLATE_MAX_BITS) - dist_tree.build_codes(dist_freqs, hdist, zdef.ZDEFLATE_MAX_BITS) - all_lengths: list[t.CInt, 288 + 32] - for i in range(hlit): all_lengths[i] = lit_tree.codes[i].bits - for i in range(hdist): all_lengths[hlit + i] = dist_tree.codes[i].bits - total_lengths: t.CInt = hlit + hdist - cl_freqs: list[t.CInt, 19] - zdeflate_count_cl_freqs(all_lengths, total_lengths, cl_freqs) - cl_tree = zhuff.zhuff_tree() - cl_tree.build_codes(cl_freqs, 19, 7) - hclen: int = 19 - while hclen > 4 and cl_tree.codes[zdef.zdeflate_codelen_order[hclen - 1]].bits == 0: hclen -= 1 - self.writer.write_bits(1 if final else 0, 1) - self.writer.write_bits(2, 2) - self.writer.write_bits(hlit - 257, 5) - self.writer.write_bits(hdist - 1, 5) - self.writer.write_bits(hclen - 4, 4) - for j in range(hclen): - self.writer.write_bits(cl_tree.codes[zdef.zdeflate_codelen_order[j]].bits, 3) - zdeflate_write_cl_encoded(all_lengths, total_lengths, c.Addr(self.writer), c.Addr(cl_tree)) - self.encode_block_data(data, length, c.Addr(lit_tree), c.Addr(dist_tree)) - - def compress_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - if self.level == 0: - self.write_stored_block(data, length, final) - elif self.strategy == 4 or length < 128: - self.write_fixed_block(data, length, final) - else: - self.write_dynamic_block(data, length, final) - - def write_stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - self.writer.stored_block(data, length, final) - - def compress(self, data: UINT8PTR, length: t.CSizeT, - out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if self.is_finished: return -2 - if not data or length == 0: - c.Set(c.Deref(out), None) - c.Set(c.Deref(out_len), 0) - return 0 - self.adler = zchecksum.zchecksum_adler32(data, length, self.adler) - memset(self.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(self.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - self.compress_block(data, length, 0) - c.Set(c.Deref(out_len), self.writer.total()) - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(c.Deref(out_len)))) - if not c.Deref(out): return -4 - memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len)) - return 0 - - def flush(self, mode: t.CInt, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if mode == 4: - if not self.is_finished: - if self.level == 0: - self.writer.write_bits(1, 1) - self.writer.write_bits(0, 2) - self.writer.align() - else: - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - self.writer.write_bits(1, 1) - self.writer.write_bits(1, 2) - lit_tree.encode_symbol(256, c.Addr(self.writer)) - self.is_finished = 1 - if self.wbits >= 0: - self.writer.align() - adler: t.CUInt32T = self.adler - self.writer.buf[self.writer.byte_pos + 0] = (adler >> 24) & 0xFF - self.writer.buf[self.writer.byte_pos + 1] = (adler >> 16) & 0xFF - self.writer.buf[self.writer.byte_pos + 2] = (adler >> 8) & 0xFF - self.writer.buf[self.writer.byte_pos + 3] = (adler >> 0) & 0xFF - self.writer.byte_pos += 4 - elif mode == 2 or mode == 3: - self.writer.write_bits(0, 1) - self.writer.write_bits(0, 2) - self.writer.align() - c.Set(c.Deref(out_len), self.writer.total()) - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(c.Deref(out_len)))) - if not c.Deref(out): return -4 - memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len)) - return 0 - - def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt: - if not dict: return -2 - use: t.CSizeT = length - if use > zdef.ZDEFLATE_WINDOW_SIZE: - dict += length - zdef.ZDEFLATE_WINDOW_SIZE - use = zdef.ZDEFLATE_WINDOW_SIZE - memcpy(self.window, dict, use) - self.window_size = t.CInt(use) - self.window_pos = t.CInt(use) - self.adler = zchecksum.zchecksum_adler32(dict, length, self.adler) - return 0 - - def copy(self) -> zdeflate_stream | t.CPtr: - z: zdeflate_stream | t.CPtr = zdef.zdef_alloc(zdeflate_stream.__sizeof__()) - if not z: return None - memcpy(z, self, zdeflate_stream.__sizeof__()) - z.writer.buf = BYTEPTR(zdef.zdef_alloc(self.writer.cap)) - if not z.writer.buf: - zdef.zdef_free(z) - return None - memcpy(z.writer.buf, self.writer.buf, self.writer.cap) - z.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - z.hash_head = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())) - z.hash_prev = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())) - if not z.window or not z.hash_head or not z.hash_prev: - if z.writer.buf: zdef.zdef_free(z.writer.buf) - zdef.zdef_free(z) - return None - memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE) - memcpy(z.hash_head, self.hash_head, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memcpy(z.hash_prev, self.hash_prev, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - return z - - def destroy(self): - if self.writer.buf: zdef.zdef_free(self.writer.buf) - if self.window: zdef.zdef_free(self.window) - if self.hash_head: zdef.zdef_free(self.hash_head) - if self.hash_prev: zdef.zdef_free(self.hash_prev) - zdef.zdef_free(self) - - - - -def zdeflate_count_freqs(lit_freqs: INTPTR, dist_freqs: INTPTR, - s: zdeflate_stream | t.CPtr, data: UINT8PTR, length: t.CSizeT): - memset(lit_freqs, 0, 288 * int.__sizeof__()) - memset(dist_freqs, 0, 32 * int.__sizeof__()) - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if s.level > 0 and pos + 2 < length: - match_len = zdeflate_stream.find_match(s, data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_freqs[len_sym] += 1 - dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1 - for i in range(match_len): - zdeflate_stream.update_hash(s, data, pos + i) - pos += match_len - else: - lit_freqs[data[pos]] += 1 - zdeflate_stream.update_hash(s, data, pos) - pos += 1 - lit_freqs[256] = 1 - - - -def zdeflate_hash(p: BYTE | t.CPtr) -> t.CUnsignedInt: - return (t.CUnsignedInt(p[0]) ^ (t.CUnsignedInt(p[1]) << 5) ^ (t.CUnsignedInt(p[2]) << 10)) & zdef.ZDEFLATE_HASH_MASK - - -def zdeflate_len_to_symbol(length: t.CInt) -> t.CInt: - for i in range(29): - if length <= zdef.zdeflate_len_base[i] + (1 << zdef.zdeflate_len_extra_bits[i]) - 1: - return 257 + i - return 285 - -def zdeflate_dist_to_symbol(dist: t.CInt) -> t.CInt: - for i in range(30): - if dist <= zdef.zdeflate_dist_base[i] + (1 << zdef.zdeflate_dist_extra_bits[i]) - 1: - return i - return 29 - -def zdeflate_count_cl_freqs(all_lengths: INTPTR, total: t.CInt, cl_freqs: INTPTR): - memset(cl_freqs, 0, 19 * int.__sizeof__()) - i: t.CInt = 0 - while i < total: - if all_lengths[i] == 0: - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == 0: run += 1 - while run > 0: - if run >= 11: - count: t.CInt = run - if count > 138: count = 138 - cl_freqs[18] += 1 - run -= count - elif run >= 3: - count: t.CInt = run - if count > 10: count = 10 - cl_freqs[17] += 1 - run -= count - else: - cl_freqs[0] += 1 - run -= 1 - while i < total and all_lengths[i] == 0: i += 1 - else: - cl_freqs[all_lengths[i]] += 1 - val: t.CInt = all_lengths[i] - i += 1 - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == val: run += 1 - while run >= 3: - count: t.CInt = run - if count > 6: count = 6 - cl_freqs[16] += 1 - run -= count - i += run - -def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt, - w: zdef.zbit_writer | t.CPtr, cl_tree: zhuff.zhuff_tree | t.CPtr): - i: t.CInt = 0 - while i < total: - if all_lengths[i] == 0: - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == 0: run += 1 - while run > 0: - if run >= 11: - count: t.CInt = run - if count > 138: count = 138 - cl_tree.encode_symbol(18, w) - w.write_bits(count - 11, 7) - run -= count - elif run >= 3: - count: t.CInt = run - if count > 10: count = 10 - cl_tree.encode_symbol(17, w) - w.write_bits(count - 3, 3) - run -= count - else: - cl_tree.encode_symbol(0, w) - run -= 1 - while i < total and all_lengths[i] == 0: i += 1 - else: - cl_tree.encode_symbol(all_lengths[i], w) - val: t.CInt = all_lengths[i] - i += 1 - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == val: run += 1 - while run >= 3: - count: t.CInt = run - if count > 6: count = 6 - cl_tree.encode_symbol(16, w) - w.write_bits(count - 3, 2) - run -= count - i += run - - - -def zdeflate_create(level: t.CInt, wbits: t.CInt, mem_level: t.CInt, strategy: t.CInt) -> zdeflate_stream | t.CPtr: - s: zdeflate_stream | t.CPtr = zdef.zdef_alloc(zdeflate_stream.__sizeof__()) - if not s: return None - memset(s, 0, zdeflate_stream.__sizeof__()) - s.writer = zdef.zbit_writer() - s.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - s.hash_head = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())) - s.hash_prev = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())) - if not s.window or not s.hash_head or not s.hash_prev: - s.destroy() - return None - memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - s.level = level - s.wbits = wbits - s.strategy = strategy - s.is_finished = 0 - s.adler = 1 - if wbits > 0: - s.writer.write_zlib_header(wbits, level) - elif wbits == 0: - s.writer.write_zlib_header(15, level) - return s - - -def zdeflate_one_shot(data: UINT8PTR, length: t.CSizeT, - level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr: - s: zdeflate_stream | t.CPtr = zdeflate_create(level, wbits, 8, 0) - if not s: return None - - memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - - s.adler = zchecksum.zchecksum_adler32(data, length, 1) - - if length == 0: - s.writer.write_bits(1, 1) - s.writer.write_bits(1, 2) - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - lit_tree.encode_symbol(256, c.Addr(s.writer)) - else: - s.compress_block(data, length, 1) - - s.is_finished = 1 - - if wbits >= 0: - s.writer.align() - adler: t.CUInt32T = s.adler - s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF - s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF - s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF - s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF - s.writer.byte_pos += 4 - c.Set(c.Deref(out_len), s.writer.total()) - result: UINT8PTR = UINT8PTR(zdef.zdef_alloc(c.Deref(out_len))) - if result: memcpy(result, s.writer.buf, c.Deref(out_len)) - s.destroy() - return result diff --git a/Test/TestProject/App/__zlib/zhuff.py b/Test/TestProject/App/__zlib/zhuff.py deleted file mode 100644 index 71c4158..0000000 --- a/Test/TestProject/App/__zlib/zhuff.py +++ /dev/null @@ -1,353 +0,0 @@ -#include -from stdint import * -import zdef -import t, c - - -ZHUFF_MAX_CODES: t.CDefine = 288 -ZHUFF_MAX_BITS: t.CDefine = 15 - -class zhuff_code: - code: UINT - bits: t.CInt - -@t.Object -class zhuff_tree: - codes: list[zhuff_code, ZHUFF_MAX_CODES] - count: t.CInt - max_bits: t.CInt - - def __init__(self): - pass - - def build_codes(self, freqs: INTPTR, count: t.CInt, max_bits: t.CInt): - lengths: list[t.CInt, ZHUFF_MAX_CODES] - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 1] - next_code: list[UINT, ZHUFF_MAX_BITS + 1] - self.count = count - self.max_bits = max_bits - self.build_code_lengths(lengths, freqs, count, max_bits) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, max_bits + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - for i in range(count): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def build_fixed_lit_tree(self): - lengths: list[t.CInt, 288] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] - self.get_fixed_lit_lengths(lengths) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(288): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, 9 + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - self.count = 288 - self.max_bits = 9 - for i in range(288): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def build_fixed_dist_tree(self): - lengths: list[t.CInt, 32] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] - self.get_fixed_dist_lengths(lengths) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(32): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, 5 + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - self.count = 32 - self.max_bits = 5 - for i in range(32): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def encode_symbol(self, symbol: int, writer: zdef.zbit_writer | t.CPtr): - if symbol < 0 or symbol >= self.count: - return - if self.codes[symbol].bits == 0: - return - writer.write_bits_rev(self.codes[symbol].code, self.codes[symbol].bits) - - - def build_code_lengths(self, lengths: t.CInt | t.CPtr, freqs: t.CInt | t.CPtr, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 2] - sort_count: t.CInt = 0 - memset(bl_count, 0, bl_count.__sizeof__()) - memset(lengths, 0, int.__sizeof__() * count) - for i in range(count): - if freqs[i] > 0: - sort_count += 1 - if sort_count == 0: return - if sort_count == 1: - for i in range(count): - if freqs[i] > 0: - lengths[i] = 1 - return - items: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - item_freqs: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - idx: t.CInt = 0 - for i in range(count): - if freqs[i] > 0: - items[idx] = i - item_freqs[idx] = freqs[i] - idx += 1 - for i in range(sort_count): - key_item: t.CInt = items[i] - key_freq: t.CInt = item_freqs[i] - j: t.CInt = i - 1 - while j >= 0 and item_freqs[j] > key_freq: - items[j + 1] = items[j] - item_freqs[j + 1] = item_freqs[j] - j -= 1 - items[j + 1] = key_item - item_freqs[j + 1] = key_freq - parent: INTPTR = INTPTR(zdef.zdef_alloc((sort_count * 2) * int.__sizeof__())) - for i in range(sort_count * 2): - parent[i] = -1 - heap: INTPTR = INTPTR(zdef.zdef_alloc((sort_count + 1) * int.__sizeof__())) - heap_size: t.CInt = 0 - for i in range(sort_count): - heap[heap_size] = i - heap_size += 1 - pos: t.CInt = heap_size - 1 - while pos > 0: - par: t.CInt = (pos - 1) / 2 - if item_freqs[heap[par]] > item_freqs[heap[pos]]: - tmp: t.CInt = heap[par] - heap[par] = heap[pos] - heap[pos] = tmp - pos = par - else: break - combined_freq: INTPTR = INTPTR(zdef.zdef_alloc((sort_count * 2) * int.__sizeof__())) - for i in range(sort_count): - combined_freq[i] = item_freqs[i] - internal: t.CInt = sort_count - while heap_size > 1: - a: t.CInt = heap[0] - heap[0] = heap[heap_size - 1] - heap_size -= 1 - pos: t.CInt = 0 - while True: - left: t.CInt = 2 * pos + 1 - right: t.CInt = 2 * pos + 2 - smallest: t.CInt = pos - if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]: - smallest = left - if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]: - smallest = right - if smallest != pos: - tmp: t.CInt = heap[pos] - heap[pos] = heap[smallest] - heap[smallest] = tmp - pos = smallest - else: break - b: t.CInt = heap[0] - heap[0] = heap[heap_size - 1] - heap_size -= 1 - pos = 0 - while True: - left: t.CInt = 2 * pos + 1 - right: t.CInt = 2 * pos + 2 - smallest: t.CInt = pos - if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]: - smallest = left - if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]: - smallest = right - if smallest != pos: - tmp: t.CInt = heap[pos] - heap[pos] = heap[smallest] - heap[smallest] = tmp - pos = smallest - else: break - if internal >= sort_count * 2 - 1: break - combined_freq[internal] = combined_freq[a] + combined_freq[b] - parent[a] = internal - parent[b] = internal - heap[heap_size] = internal - heap_size += 1 - pos = heap_size - 1 - while pos > 0: - par: t.CInt = (pos - 1) / 2 - if combined_freq[heap[par]] > combined_freq[heap[pos]]: - tmp: t.CInt = heap[par] - heap[par] = heap[pos] - heap[pos] = tmp - pos = par - else: break - internal += 1 - for i in range(sort_count): - node: t.CInt = i - length: t.CInt = 0 - while parent[node] >= 0: - length += 1 - node = parent[node] - lengths[items[i]] = length - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - overflow: t.CInt = 0 - for i in range(count): - if lengths[i] > max_bits: - overflow += 1 - bl_count[lengths[i]] -= 1 - lengths[i] = max_bits - bl_count[max_bits] += 1 - while overflow > 0: - bits: t.CInt = max_bits - 1 - while bits > 0 and bl_count[bits] == 0: - bits -= 1 - if bits == 0: break - bl_count[bits] -= 1 - bl_count[bits + 1] += 2 - bl_count[max_bits] -= 1 - overflow -= 2 - sorted_items: INTPTR = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - si: t.CInt = 0 - for i in range(count): - if freqs[i] > 0: - sorted_items[si] = i - si += 1 - for i in range(si - 1): - for j in range(i + 1, si): - if lengths[sorted_items[i]] < lengths[sorted_items[j]]: - tmp: t.CInt = sorted_items[i] - sorted_items[i] = sorted_items[j] - sorted_items[j] = tmp - sidx: t.CInt = 0 - for bits in range(max_bits, 1, -1): - n: t.CInt = bl_count[bits] - while n > 0 and sidx < si: - lengths[sorted_items[sidx]] = bits - sidx += 1 - n -= 1 - zdef.zdef_free(sorted_items) - zdef.zdef_free(heap) - zdef.zdef_free(parent) - zdef.zdef_free(combined_freq) - zdef.zdef_free(item_freqs) - zdef.zdef_free(items) - - def get_fixed_lit_lengths(self, lengths: INTPTR): - for i in range( 0, 143 + 1): lengths[i] = 8 - for i in range(143 + 1, 255 + 1): lengths[i] = 9 - for i in range(255 + 1, 279 + 1): lengths[i] = 7 - for i in range(279 + 1, 287 + 1): lengths[i] = 8 - - def get_fixed_dist_lengths(self, lengths: INTPTR): - for i in range(32): - lengths[i] = 5 - - def build_tree_from_lengths(self, lengths: INTPTR, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] - - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - - code: UINT = 0 - next_code[0] = 0 - for bits in range(1, max_bits + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - - self.count = count - self.max_bits = max_bits - for i in range(count): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - -class zhuff_decode_node: - children: list[t.CInt, 2] - symbol: t.CInt - - -@t.Object -class zhuff_decode_tree: - nodes: list[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] - node_count: t.CInt - root: t.CInt - - def __init__(self): - pass - - def build_decode_tree(self, ht: zhuff_tree | t.CPtr): - self.node_count = 1 - self.root = 0 - self.nodes[0].children[0] = -1 - self.nodes[0].children[1] = -1 - self.nodes[0].symbol = -1 - for i in range(ht.count): - if ht.codes[i].bits == 0: continue - node: int = 0 - for bit in range(ht.codes[i].bits - 1, -1, -1): - dir: t.CInt = (ht.codes[i].code >> bit) & 1 - if bit > 0: - # Internal node: traverse or create - if self.nodes[node].children[dir] == -1: - new_node: int = self.node_count - self.node_count += 1 - self.nodes[new_node].children[0] = -1 - self.nodes[new_node].children[1] = -1 - self.nodes[new_node].symbol = -1 - self.nodes[node].children[dir] = new_node - node = self.nodes[node].children[dir] - else: - # Leaf: bit 0 - set symbol on the child - if self.nodes[node].children[dir] == -1: - leaf: int = self.node_count - self.node_count += 1 - self.nodes[leaf].children[0] = -1 - self.nodes[leaf].children[1] = -1 - self.nodes[leaf].symbol = i - self.nodes[node].children[dir] = leaf - else: - self.nodes[self.nodes[node].children[dir]].symbol = i - - def decode_symbol(self, reader: zdef.zbit_reader | t.CPtr) -> t.CInt: - node: int = self.root - while self.nodes[node].symbol == -1: - bit: t.CUnsignedInt - if reader.read_bits(1, c.Addr(bit)) != 0: return -1 - dir: t.CInt = t.CInt(bit) - if self.nodes[node].children[dir] == -1: return -1 - node = self.nodes[node].children[dir] - return self.nodes[node].symbol diff --git a/Test/TestProject/App/__zlib/zinflate.py b/Test/TestProject/App/__zlib/zinflate.py deleted file mode 100644 index efdcded..0000000 --- a/Test/TestProject/App/__zlib/zinflate.py +++ /dev/null @@ -1,454 +0,0 @@ -from stdint import * -import zinflate -import zchecksum -import zdef -import zhuff -import string -import t, c - - -@t.Object -class zinflate_stream: - reader: zdef.zbit_reader - - window: BYTEPTR - window_pos: t.CInt - window_size: t.CInt - - wbits: t.CInt - is_finished: t.CInt - is_initialized: t.CInt - - header_parsed: t.CInt - is_gzip: t.CInt - - adler: t.CUInt32T - crc: t.CUInt32T - - output: BYTEPTR - output_len: t.CSizeT - output_cap: t.CSizeT - - input_data: t.CConst | BYTEPTR - input_len: t.CSizeT - input_pos: t.CSizeT - - max_length: t.CSizeT - - def __init__(self): - pass - - def output_byte(self, byte: BYTE): - if self.max_length > 0 and self.output_len >= self.max_length: return - - if self.output_len >= self.output_cap: - new_cap: t.CSizeT = self.output_cap * 2 - if new_cap < 256: new_cap = 256 - new_buf: BYTEPTR = BYTEPTR(zdef.zdef_alloc(new_cap)) - if not new_buf: return - memcpy(new_buf, self.output, self.output_len) - zdef.zdef_free(self.output) - self.output = new_buf - self.output_cap = new_cap - self.output[self.output_len] = byte - self.output_len += 1 - self.window[self.window_pos & (zdef.ZDEFLATE_WINDOW_SIZE - 1)] = byte - self.window_pos += 1 - - - def parse_header(self) -> t.CInt: - if self.header_parsed: return 0 - if self.wbits < 0: - self.header_parsed = 1 - self.is_gzip = 0 - return 0 - if self.input_pos + 2 > self.input_len: return -3 - b0: BYTE = self.input_data[self.input_pos] - b1: BYTE = self.input_data[self.input_pos + 1] - if b0 == 0x1F and b1 == 0x8B: - self.is_gzip = 1 - if self.input_pos + 10 > self.input_len: return -3 - self.input_pos += 10 - flg: BYTE = self.input_data[self.input_pos - 6] - if flg & 0x04: - if self.input_pos + 2 > self.input_len: return -3 - xlen: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8) - self.input_pos += 2 + xlen - if flg & 0x08: - while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1 - self.input_pos += 1 - if flg & 0x10: - while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1 - self.input_pos += 1 - if flg & 0x02: - self.input_pos += 2 - if self.input_pos > self.input_len: return -3 - else: - self.is_gzip = 0 - if (b0 * 256 + b1) % 31 != 0: return -3 - cm: t.CInt = b0 & 0x0F - if cm != 8: return -3 - self.input_pos += 2 - self.header_parsed = 1 - return 0 - - - def read_bits_from_input(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits): - if self.input_pos >= self.input_len: return -3 - if self.input_data[self.input_pos] & (UINT(1) << (self.reader.bit_pos)): - val |= (UINT(1) << i) - self.reader.bit_pos += 1 - if self.reader.bit_pos == 8: - self.reader.bit_pos = 0 - self.input_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - - def read_huffman(self, dt: zhuff.zhuff_decode_tree | t.CPtr) -> t.CInt: - node: int = dt.root - while dt.nodes[node].symbol == -1: - bit: UINT - if self.read_bits_from_input(1, c.Addr(bit)) != 0: return -1 - dir: int = t.CInt(bit) - if dt.nodes[node].children[dir] == -1: return -3 - node = dt.nodes[node].children[dir] - return dt.nodes[node].symbol - - def inflate_block_stored(self) -> t.CInt: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 4 > self.input_len: return -3 - length: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8) - nlen: UINT = self.input_data[self.input_pos + 2] | (self.input_data[self.input_pos + 3] << 8) - self.input_pos += 4 - if (length ^ nlen) != 0xFFFF: return -3 - if self.input_pos + length > self.input_len: return -3 - i: t.CUnsignedInt - for i in range(length): - self.output_byte(self.input_data[self.input_pos]) - self.input_pos += 1 - return 0 - - - def inflate_block_fixed(self) -> t.CInt: - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - dist_tree.build_fixed_dist_tree() - - lit_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(zhuff.zhuff_decode_tree.__sizeof__()) - dist_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(zhuff.zhuff_decode_tree.__sizeof__()) - if not lit_dt or not dist_dt: - if lit_dt: zdef.zdef_free(lit_dt) - if dist_dt: zdef.zdef_free(dist_dt) - return -4 - memset(lit_dt, 0, zhuff.zhuff_decode_tree.__sizeof__()) - memset(dist_dt, 0, zhuff.zhuff_decode_tree.__sizeof__()) - lit_dt.build_decode_tree(c.Addr(lit_tree)) - dist_dt.build_decode_tree(c.Addr(dist_tree)) - - result: t.CInt = 0 - while True: - if self.max_length > 0 and self.output_len >= self.max_length: break - - sym: t.CInt = self.read_huffman(lit_dt) - if sym < 0: - result = -3 - break - if sym == 256: break - if sym < 256: - self.output_byte(BYTE(sym)) - else: - len_idx: t.CInt = sym - 257 - if len_idx < 0 or len_idx >= 29: - result = -3 - break - length: t.CInt = zdef.zdeflate_len_base[len_idx] - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: - result = -3 - break - length += extra_val - - dist_sym: t.CInt = self.read_huffman(dist_dt) - if dist_sym < 0 or dist_sym >= 30: - result = -3 - break - dist: t.CInt = zdef.zdeflate_dist_base[dist_sym] - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: - result = -3 - break - dist += extra_val - - for i in range(length): - if self.max_length > 0 and self.output_len >= self.max_length: break - src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1) - byte: BYTE = self.window[src_pos] - self.output_byte(byte) - - zdef.zdef_free(lit_dt) - zdef.zdef_free(dist_dt) - return result - - - def inflate_block_dynamic(self) -> t.CInt: - hlit_val: UINT - hdist_val: UINT - hclen_val: UINT - if self.read_bits_from_input(5, c.Addr(hlit_val)) != 0: return -3 - if self.read_bits_from_input(5, c.Addr(hdist_val)) != 0: return -3 - if self.read_bits_from_input(4, c.Addr(hclen_val)) != 0: return -3 - - hlit: t.CInt = t.CInt(hlit_val) + 257 - hdist: t.CInt = t.CInt(hdist_val) + 1 - hclen: t.CInt = t.CInt(hclen_val) + 4 - - cl_lengths: list[t.CInt, 19] - memset(cl_lengths, 0, cl_lengths.__sizeof__()) - for i in range(hclen): - len_val: UINT - if self.read_bits_from_input(3, c.Addr(len_val)) != 0: return -3 - cl_lengths[zdef.zdeflate_codelen_order[i]] = t.CInt(len_val) - - cl_tree = zhuff.zhuff_tree() - cl_tree.build_tree_from_lengths(cl_lengths, 19, 7) - - cl_dt = zhuff.zhuff_decode_tree() - cl_dt.build_decode_tree(c.Addr(cl_tree)) - - total: t.CInt = hlit + hdist - all_lengths: t.CInt | t.CPtr = zdef.zdef_alloc(total * int.__sizeof__()) - if not all_lengths: return -4 - - idx: t.CInt = 0 - while idx < total: - sym: t.CInt = self.read_huffman(c.Addr(cl_dt)) - if sym < 0 or sym > 18: - zdef.zdef_free(all_lengths) - return -3 - if sym < 16: - all_lengths[idx] = sym - idx += 1 - elif sym == 16: - rep: UINT - if self.read_bits_from_input(2, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 3 - if idx == 0 or idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - prev: t.CInt = all_lengths[idx - 1] - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = prev - idx += 1 - elif sym == 17: - rep: t.CUnsignedInt - if self.read_bits_from_input(3, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 3 - if idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = 0 - idx += 1 - else: - rep: t.CUnsignedInt - if self.read_bits_from_input(7, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 11 - if idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = 0 - idx += 1 - - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - - lit_lengths: list[t.CInt, 288] - memset(lit_lengths, 0, lit_lengths.__sizeof__()) - for i in range(hlit): - lit_lengths[i] = all_lengths[i] - lit_tree.build_tree_from_lengths(lit_lengths, hlit, zdef.ZDEFLATE_MAX_BITS) - - dist_lengths: list[t.CInt, 32] - memset(dist_lengths, 0, dist_lengths.__sizeof__()) - for i in range(hdist): - dist_lengths[i] = all_lengths[hlit + i] - dist_tree.build_tree_from_lengths(dist_lengths, hdist, zdef.ZDEFLATE_MAX_BITS) - - zdef.zdef_free(all_lengths) - - lit_dt = zhuff.zhuff_decode_tree() - dist_dt = zhuff.zhuff_decode_tree() - lit_dt.build_decode_tree(c.Addr(lit_tree)) - dist_dt.build_decode_tree(c.Addr(dist_tree)) - - while True: - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - sym: t.CInt = self.read_huffman(c.Addr(lit_dt)) - if sym < 0: return -3 - if sym == 256: return 0 - if sym < 256: - self.output_byte(BYTE(sym)) - else: - len_idx: t.CInt = sym - 257 - if len_idx < 0 or len_idx >= 29: return -3 - length: t.CInt = zdef.zdeflate_len_base[len_idx] - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3 - length += extra_val - dist_sym: t.CInt = self.read_huffman(c.Addr(dist_dt)) - if dist_sym < 0 or dist_sym >= 30: return -3 - dist: t.CInt = zdef.zdeflate_dist_base[dist_sym] - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3 - dist += extra_val - for i in range(length): - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1) - byte: BYTE = self.window[src_pos] - self.output_byte(byte) - - def inflate_stream(self) -> t.CInt: - err: t.CInt = self.parse_header() - if err != 0: return err - while not self.is_finished: - bfinal_val: UINT - btype_val: UINT - if self.read_bits_from_input(1, c.Addr(bfinal_val)) != 0: return -3 - if self.read_bits_from_input(2, c.Addr(btype_val)) != 0: return -3 - bfinal: t.CInt = t.CInt(bfinal_val) - btype: t.CInt = t.CInt(btype_val) - if btype == 0: - err = self.inflate_block_stored() - elif btype == 1: - err = self.inflate_block_fixed() - elif btype == 2: - err = self.inflate_block_dynamic() - else: - return -3 - if err != 0: return err - if bfinal: self.is_finished = 1 - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - if self.is_gzip: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 8 <= self.input_len: - self.crc = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 0) | - (t.CUInt32T(self.input_data[self.input_pos + 1]) << 8) | - (t.CUInt32T(self.input_data[self.input_pos + 2]) << 16) | - (t.CUInt32T(self.input_data[self.input_pos + 3]) << 24)) - self.input_pos += 8 - elif self.wbits >= 0: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 4 <= self.input_len: - self.adler = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 24) | - (t.CUInt32T(self.input_data[self.input_pos + 1]) << 16) | - (t.CUInt32T(self.input_data[self.input_pos + 2]) << 8) | - (t.CUInt32T(self.input_data[self.input_pos + 3]) << 0)) - self.input_pos += 4 - return 0 - - def decompress(self, data: UINT8PTR, length: t.CSizeT, - max_length: t.CSizeT, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if not self.is_initialized: return -2 - self.input_data = data - self.input_len = length - self.input_pos = 0 - self.reader.bit_pos = 0 - self.output_len = 0 - self.max_length = max_length - err: t.CInt = self.inflate_stream() - if err != 0: return err - c.Set(c.Deref(out_len), self.output_len) - if self.output_len == 0: - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(1))) - else: - dst: UINT8PTR = UINT8PTR(zdef.zdef_alloc(self.output_len)) - c.Set(c.Deref(out), dst) - if dst: - memcpy(dst, self.output, self.output_len) - return 0 - - def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt: - if not dict: return -2 - use: t.CSizeT = length - if use > zdef.ZDEFLATE_WINDOW_SIZE: - dict += length - zdef.ZDEFLATE_WINDOW_SIZE - use = zdef.ZDEFLATE_WINDOW_SIZE - memcpy(self.window, dict, use) - self.window_pos = t.CInt(use) - return 0 - - def copy(self) -> zinflate_stream | t.CPtr: - z: zinflate_stream | t.CPtr = zdef.zdef_alloc(zinflate_stream.__sizeof__()) - if not z: return None - memcpy(z, self, zinflate_stream.__sizeof__()) - z.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - z.output = BYTEPTR(zdef.zdef_alloc(self.output_cap)) - if not z.window or not z.output: - zinflate_stream.destroy(z) - return None - memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE) - memcpy(z.output, self.output, self.output_cap) - return z - - def destroy(self): - if not self: return - if self.window: zdef.zdef_free(self.window) - if self.output: zdef.zdef_free(self.output) - zdef.zdef_free(self) - - -def zinflate_one_shot(data: UINT8PTR, length: t.CSizeT, - wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr: - s: zinflate_stream | t.CPtr = zinflate_create(wbits) - if not s: return None - out: t.CUInt8T | t.CPtr = None - err: t.CInt = s.decompress(data, length, 0, c.Addr(out), out_len) - s.destroy() - if err != 0: return None - return out - - -def zinflate_create(wbits: t.CInt) -> zinflate_stream | t.CPtr: - s: zinflate_stream | t.CPtr = zdef.zdef_alloc(zinflate_stream.__sizeof__()) - if not s: return None - memset(s, 0, zinflate_stream.__sizeof__()) - s.wbits = wbits - s.is_initialized = 1 - s.adler = 1 - s.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - s.output = BYTEPTR(zdef.zdef_alloc(256)) - s.output_cap = 256 - s.output_len = 0 - s.max_length = 0 - if not s.window or not s.output: - s.destroy() - return None - return s diff --git a/Test/TestProject/App/test_zlib.py b/Test/TestProject/App/test_zlib.py index 3961883..9441a04 100644 --- a/Test/TestProject/App/test_zlib.py +++ b/Test/TestProject/App/test_zlib.py @@ -2,7 +2,9 @@ from stdint import * import zlib.pyzlib as pyzlib import zlib.zhuff as zhuff import zlib.zdef as zdef -from stdio import printf, strlen +from stdio import printf +from string import strlen, memcmp, memcpy, memset +from stdlib import malloc, free, realloc import stdlib import string import mpool diff --git a/Test/TestProject/output/067c78e9f121dce3.deps.json b/Test/TestProject/output/067c78e9f121dce3.deps.json index 52dd90d..b16da63 100644 --- a/Test/TestProject/output/067c78e9f121dce3.deps.json +++ b/Test/TestProject/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestProject/output/439f5b503003443f.deps.json b/Test/TestProject/output/0c04ab530bb9cfa4.deps.json similarity index 54% rename from Test/TestProject/output/439f5b503003443f.deps.json rename to Test/TestProject/output/0c04ab530bb9cfa4.deps.json index 1932abc..33f0073 100644 --- a/Test/TestProject/output/439f5b503003443f.deps.json +++ b/Test/TestProject/output/0c04ab530bb9cfa4.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file +{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/0d13cde396f4a15f.deps.json b/Test/TestProject/output/0d13cde396f4a15f.deps.json index d33054c..1343411 100644 --- a/Test/TestProject/output/0d13cde396f4a15f.deps.json +++ b/Test/TestProject/output/0d13cde396f4a15f.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f"} \ No newline at end of file diff --git a/Test/TestProject/output/0d4517fd5afeb330.deps.json b/Test/TestProject/output/0d4517fd5afeb330.deps.json index 6a762c7..d8eb6a9 100644 --- a/Test/TestProject/output/0d4517fd5afeb330.deps.json +++ b/Test/TestProject/output/0d4517fd5afeb330.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330"} \ No newline at end of file diff --git a/Test/TestProject/output/29813d57621099a9.deps.json b/Test/TestProject/output/29813d57621099a9.deps.json index 94efaa6..3d535c3 100644 --- a/Test/TestProject/output/29813d57621099a9.deps.json +++ b/Test/TestProject/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/2d7f623c6e3004ce.deps.json b/Test/TestProject/output/2d7f623c6e3004ce.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/2d7f623c6e3004ce.deps.json +++ b/Test/TestProject/output/2d7f623c6e3004ce.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/2e756dd336749fc2.deps.json b/Test/TestProject/output/2e756dd336749fc2.deps.json index 4690763..a9ee6fb 100644 --- a/Test/TestProject/output/2e756dd336749fc2.deps.json +++ b/Test/TestProject/output/2e756dd336749fc2.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/3d1656b26b38b359.deps.json b/Test/TestProject/output/3d1656b26b38b359.deps.json deleted file mode 100644 index 12b6ecc..0000000 --- a/Test/TestProject/output/3d1656b26b38b359.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/3ee89b588a1da94f.deps.json b/Test/TestProject/output/3ee89b588a1da94f.deps.json index 942ae4b..93da396 100644 --- a/Test/TestProject/output/3ee89b588a1da94f.deps.json +++ b/Test/TestProject/output/3ee89b588a1da94f.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/3f7c5e78d8652535.deps.json b/Test/TestProject/output/3f7c5e78d8652535.deps.json index 81827d5..83b79bc 100644 --- a/Test/TestProject/output/3f7c5e78d8652535.deps.json +++ b/Test/TestProject/output/3f7c5e78d8652535.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/4638d411fd53fef0.deps.json b/Test/TestProject/output/4638d411fd53fef0.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/4638d411fd53fef0.deps.json +++ b/Test/TestProject/output/4638d411fd53fef0.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/4bf3e0150b9e02e9.deps.json b/Test/TestProject/output/4bf3e0150b9e02e9.deps.json new file mode 100644 index 0000000..83b79bc --- /dev/null +++ b/Test/TestProject/output/4bf3e0150b9e02e9.deps.json @@ -0,0 +1 @@ +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/58121a0fb0ca7466.deps.json b/Test/TestProject/output/58121a0fb0ca7466.deps.json index c84d4ea..a7b9b5c 100644 --- a/Test/TestProject/output/58121a0fb0ca7466.deps.json +++ b/Test/TestProject/output/58121a0fb0ca7466.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/5a6a2137958c28c5.deps.json b/Test/TestProject/output/5a6a2137958c28c5.deps.json index 5d7d4f0..0e72337 100644 --- a/Test/TestProject/output/5a6a2137958c28c5.deps.json +++ b/Test/TestProject/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/output/68c4fe4b12c908e3.deps.json b/Test/TestProject/output/68c4fe4b12c908e3.deps.json index 94efaa6..83b79bc 100644 --- a/Test/TestProject/output/68c4fe4b12c908e3.deps.json +++ b/Test/TestProject/output/68c4fe4b12c908e3.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/6aee24fdefa3cbc0.deps.json b/Test/TestProject/output/6aee24fdefa3cbc0.deps.json index 12b6ecc..83b79bc 100644 --- a/Test/TestProject/output/6aee24fdefa3cbc0.deps.json +++ b/Test/TestProject/output/6aee24fdefa3cbc0.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json b/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json index f57fb55..da2931b 100644 --- a/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestProject/output/7e4cef8dd61984f0.deps.json b/Test/TestProject/output/7e4cef8dd61984f0.deps.json deleted file mode 100644 index 94efaa6..0000000 --- a/Test/TestProject/output/7e4cef8dd61984f0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/88e3e48eab9e1653.deps.json b/Test/TestProject/output/88e3e48eab9e1653.deps.json index 81827d5..83b79bc 100644 --- a/Test/TestProject/output/88e3e48eab9e1653.deps.json +++ b/Test/TestProject/output/88e3e48eab9e1653.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/8e0d8fdba991b3b4.deps.json b/Test/TestProject/output/8e0d8fdba991b3b4.deps.json index ad7c768..d8f67bb 100644 --- a/Test/TestProject/output/8e0d8fdba991b3b4.deps.json +++ b/Test/TestProject/output/8e0d8fdba991b3b4.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/8f88a3374d5335cc.deps.json b/Test/TestProject/output/8f88a3374d5335cc.deps.json new file mode 100644 index 0000000..5d3e5fd --- /dev/null +++ b/Test/TestProject/output/8f88a3374d5335cc.deps.json @@ -0,0 +1 @@ +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/94496ec50b0d13fc.deps.json b/Test/TestProject/output/94496ec50b0d13fc.deps.json index e296236..d676e78 100644 --- a/Test/TestProject/output/94496ec50b0d13fc.deps.json +++ b/Test/TestProject/output/94496ec50b0d13fc.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc"} \ No newline at end of file diff --git a/Test/TestProject/output/a9fa0f6200c09e65.deps.json b/Test/TestProject/output/a9fa0f6200c09e65.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/a9fa0f6200c09e65.deps.json +++ b/Test/TestProject/output/a9fa0f6200c09e65.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/abf9ce3160c9279e.deps.json b/Test/TestProject/output/abf9ce3160c9279e.deps.json index 9c8f69c..a56224b 100644 --- a/Test/TestProject/output/abf9ce3160c9279e.deps.json +++ b/Test/TestProject/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TestProject/output/b0267503e816efc4.deps.json b/Test/TestProject/output/b0267503e816efc4.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/b0267503e816efc4.deps.json +++ b/Test/TestProject/output/b0267503e816efc4.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json b/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json index 7338a29..28ea2c2 100644 --- a/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json +++ b/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json index 5d7d4f0..0e72337 100644 --- a/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/output/c3eb91093118e1e1.deps.json b/Test/TestProject/output/c3eb91093118e1e1.deps.json index 827d74a..0a3191e 100644 --- a/Test/TestProject/output/c3eb91093118e1e1.deps.json +++ b/Test/TestProject/output/c3eb91093118e1e1.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json b/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json index 12b6ecc..83b79bc 100644 --- a/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/d282a7cb3385ecf0.deps.json b/Test/TestProject/output/d282a7cb3385ecf0.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/d282a7cb3385ecf0.deps.json +++ b/Test/TestProject/output/d282a7cb3385ecf0.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json b/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json index 94efaa6..ef1d5e7 100644 --- a/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json +++ b/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "d63d2c2a2bd9bd2a", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/fa3691e66b426950.deps.json b/Test/TestProject/output/fa3691e66b426950.deps.json index 5d7d4f0..0e72337 100644 --- a/Test/TestProject/output/fa3691e66b426950.deps.json +++ b/Test/TestProject/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "binascii": "3d1656b26b38b359", "BINASCII": "3d1656b26b38b359", "vipermath": "3f7c5e78d8652535", "test_zlib": "439f5b503003443f", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b", "stdlib": "7538e542cab4c1d5", "base64": "7e4cef8dd61984f0", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/temp/439f5b503003443f.pyi b/Test/TestProject/temp/0c04ab530bb9cfa4.pyi similarity index 92% rename from Test/TestProject/temp/439f5b503003443f.pyi rename to Test/TestProject/temp/0c04ab530bb9cfa4.pyi index 259fce6..e520473 100644 --- a/Test/TestProject/temp/439f5b503003443f.pyi +++ b/Test/TestProject/temp/0c04ab530bb9cfa4.pyi @@ -8,7 +8,9 @@ from stdint import * import zlib.pyzlib as pyzlib import zlib.zhuff as zhuff import zlib.zdef as zdef -from stdio import printf, strlen +from stdio import printf +from string import strlen, memcmp, memcpy, memset +from stdlib import malloc, free, realloc import stdlib import string import mpool diff --git a/Test/TestProject/temp/7e4cef8dd61984f0.pyi b/Test/TestProject/temp/4bf3e0150b9e02e9.pyi similarity index 94% rename from Test/TestProject/temp/7e4cef8dd61984f0.pyi rename to Test/TestProject/temp/4bf3e0150b9e02e9.pyi index d5c249f..bd213f3 100644 --- a/Test/TestProject/temp/7e4cef8dd61984f0.pyi +++ b/Test/TestProject/temp/4bf3e0150b9e02e9.pyi @@ -4,7 +4,6 @@ Module: base64 """ -import binascii import t, c b64_tab: t.CExtern | list[t.CChar, None] diff --git a/Test/TestProject/temp/6c2029b306556c00.pyi b/Test/TestProject/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/TestProject/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/TestProject/temp/7538e542cab4c1d5.pyi b/Test/TestProject/temp/7538e542cab4c1d5.pyi deleted file mode 100644 index b5313af..0000000 --- a/Test/TestProject/temp/7538e542cab4c1d5.pyi +++ /dev/null @@ -1,18 +0,0 @@ -""" -Auto-generated Python stub file from stdlib.py -Module: stdlib -""" - -import c - - -from stdint import * -import t - -def malloc(size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def calloc(nmemb: UINT, size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def realloc(p: str, p2: t.CLong | t.CLong) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/TestProject/temp/3d1656b26b38b359.pyi b/Test/TestProject/temp/8f88a3374d5335cc.pyi similarity index 98% rename from Test/TestProject/temp/3d1656b26b38b359.pyi rename to Test/TestProject/temp/8f88a3374d5335cc.pyi index 6b4a08a..374b741 100644 --- a/Test/TestProject/temp/3d1656b26b38b359.pyi +++ b/Test/TestProject/temp/8f88a3374d5335cc.pyi @@ -5,7 +5,6 @@ Module: binascii import t, c -import stdint HEX_CHARS: t.CExtern | list[t.CChar, None] HEX_VALS: t.CExtern | list[t.CInt, 256] diff --git a/Test/TestProject/temp/_sha1_map.txt b/Test/TestProject/temp/_sha1_map.txt index 634b5ca..eefe6e8 100644 --- a/Test/TestProject/temp/_sha1_map.txt +++ b/Test/TestProject/temp/_sha1_map.txt @@ -1,22 +1,22 @@ +0c04ab530bb9cfa4:test_zlib.py 0d13cde396f4a15f:includes/hashlib\__sha1.py 0d4517fd5afeb330:includes/hashlib\__sha256.py 2d7f623c6e3004ce:includes/zlib\zdeflate.py 2e756dd336749fc2:test_numpy.py -3d1656b26b38b359:includes/binascii.py 3ee89b588a1da94f:BINASCII.py 3f7c5e78d8652535:includes/vipermath.py -439f5b503003443f:test_zlib.py 4638d411fd53fef0:includes/zlib\zchecksum.py +4bf3e0150b9e02e9:includes/base64.py 56cdd754a8a09347:includes/stdint.py 58121a0fb0ca7466:main.py 5a6a2137958c28c5:includes/w32\win32base.py 68c4fe4b12c908e3:includes/mpool.py 6aee24fdefa3cbc0:includes/string.py +6c2029b306556c00:includes/stdlib.py 73edbcf76e32d00b:includes/stdio.py -7538e542cab4c1d5:includes/stdlib.py -7e4cef8dd61984f0:includes/base64.py 88e3e48eab9e1653:includes/hashlib\__sha512.py 8e0d8fdba991b3b4:config.py +8f88a3374d5335cc:includes/binascii.py 94496ec50b0d13fc:includes/hashlib\__md5.py 96837bcc64032444:includes/hashlib\__init__.py a9fa0f6200c09e65:includes/zlib\zdef.py diff --git a/Test/TestProject/temp/_shared_sym.pkl b/Test/TestProject/temp/_shared_sym.pkl index e38d1e8..fa9d5e7 100644 Binary files a/Test/TestProject/temp/_shared_sym.pkl and b/Test/TestProject/temp/_shared_sym.pkl differ diff --git a/Test/TestProject2/project.json b/Test/TestProject2/project.json index aa634e2..d16b2c0 100644 --- a/Test/TestProject2/project.json +++ b/Test/TestProject2/project.json @@ -17,6 +17,10 @@ "includes": [ "./includes" ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, "options": { "slice_level": 3, "target": "llvm", diff --git a/Test/TestProject2/temp/09ba6d4617920d26.pyi b/Test/TestProject2/temp/09ba6d4617920d26.pyi index 65f16df..bb148a9 100644 --- a/Test/TestProject2/temp/09ba6d4617920d26.pyi +++ b/Test/TestProject2/temp/09ba6d4617920d26.pyi @@ -14,4 +14,4 @@ import zc.test as test import zc.logic_test as logic import zc.class_test as class_test -def main() -> stdint.INT | t.State: pass +def main() -> stdint.INT: pass diff --git a/Test/TestProject2/temp/73edbcf76e32d00b.pyi b/Test/TestProject2/temp/73edbcf76e32d00b.pyi index 0b25044..ef712e3 100644 --- a/Test/TestProject2/temp/73edbcf76e32d00b.pyi +++ b/Test/TestProject2/temp/73edbcf76e32d00b.pyi @@ -6,21 +6,21 @@ Module: stdio import t, c -def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass -def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass -def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass -def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass -def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass -def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass -def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport | t.State: pass +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass -def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport | t.State: pass +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass stdin: t.CExtern | t.CVoid | t.CPtr diff --git a/Test/TestProject2/temp/75583f20a922ab2e.pyi b/Test/TestProject2/temp/75583f20a922ab2e.pyi index 8a40bd2..10da71f 100644 --- a/Test/TestProject2/temp/75583f20a922ab2e.pyi +++ b/Test/TestProject2/temp/75583f20a922ab2e.pyi @@ -7,32 +7,32 @@ Module: zc.test import config import t, c -def AboutSizeTWhileTest(length: t.CSizeT) -> t.CVoid | t.State: pass +def AboutSizeTWhileTest(length: t.CSizeT) -> t.CInt: pass -def MathBasicTest(x: t.CInt, y: t.CInt) -> t.CInt | t.State: pass +def MathBasicTest(x: t.CInt, y: t.CInt) -> t.CInt: pass -def MathAdvancedTest(value: t.CInt) -> t.CInt | t.State: pass +def MathAdvancedTest(value: t.CInt) -> t.CInt: pass -def WhileWithElifElseTest(start: t.CInt, end: t.CInt) -> t.CVoid | t.State: pass +def WhileWithElifElseTest(start: t.CInt, end: t.CInt) -> t.CInt: pass -def NestedWhileWithMacrosTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CVoid | t.State: pass +def NestedWhileWithMacrosTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CInt: pass -def ComplexConditionTest(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CVoid | t.State: pass +def ComplexConditionTest(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CInt: pass -def RetryLoopTest(retry_count: t.CInt) -> t.CInt | t.State: pass +def RetryLoopTest(retry_count: t.CInt) -> t.CInt: pass -def BitwiseOperationsTest(value: t.CInt) -> t.CInt | t.State: pass +def BitwiseOperationsTest(value: t.CInt) -> t.CInt: pass -def CompoundAssignmentMathTest(a: t.CInt, b: t.CInt) -> t.CInt | t.State: pass +def CompoundAssignmentMathTest(a: t.CInt, b: t.CInt) -> t.CInt: pass -def PowerAndModuloTest(base: t.CInt, exponent: t.CInt) -> t.CInt | t.State: pass +def PowerAndModuloTest(base: t.CInt, exponent: t.CInt) -> t.CInt: pass -def MixedArithmeticTest(x: t.CInt, y: t.CInt, z: t.CInt) -> t.CInt | t.State: pass +def MixedArithmeticTest(x: t.CInt, y: t.CInt, z: t.CInt) -> t.CInt: pass -def MathWithWhileLoopTest(start: t.CInt, count: t.CInt) -> t.CInt | t.State: pass +def MathWithWhileLoopTest(start: t.CInt, count: t.CInt) -> t.CInt: pass -def ComplexNestedMathTest(a: t.CInt, b: t.CInt) -> t.CInt | t.State: pass +def ComplexNestedMathTest(a: t.CInt, b: t.CInt) -> t.CInt: pass -def ConditionalMathChainTest(value: t.CInt) -> t.CInt | t.State: pass +def ConditionalMathChainTest(value: t.CInt) -> t.CInt: pass -def BitManipulationMathTest(value: t.CInt) -> t.CInt | t.State: pass +def BitManipulationMathTest(value: t.CInt) -> t.CInt: pass diff --git a/Test/TestProject2/temp/_shared_sym.pkl b/Test/TestProject2/temp/_shared_sym.pkl index 94768a3..28eaf6a 100644 Binary files a/Test/TestProject2/temp/_shared_sym.pkl and b/Test/TestProject2/temp/_shared_sym.pkl differ diff --git a/Test/TestProject2/temp/a7dab00d979c009c.pyi b/Test/TestProject2/temp/a7dab00d979c009c.pyi index 0b959e8..5677a22 100644 --- a/Test/TestProject2/temp/a7dab00d979c009c.pyi +++ b/Test/TestProject2/temp/a7dab00d979c009c.pyi @@ -19,48 +19,48 @@ class Student(t.Object): name: t.CChar | t.CPtr age: t.CInt score: t.CInt - def __init__(self: Student, n: t.CChar | t.CPtr, a: t.CInt, s: t.CInt) -> t.CVoid | t.State: pass - def get_age(self: Student) -> t.CInt | t.State: pass - def get_score(self: Student) -> t.CInt | t.State: pass + def __init__(self: Student, n: t.CChar | t.CPtr, a: t.CInt, s: t.CInt) -> t.CInt: pass + def get_age(self: Student) -> t.CInt: pass + def get_score(self: Student) -> t.CInt: pass class Counter(t.Object): value: t.CInt - def __init__(self: Counter, initial: t.CInt) -> t.CVoid | t.State: pass - def increment(self: Counter) -> t.CVoid | t.State: pass - def get_value(self: Counter) -> t.CInt | t.State: pass + def __init__(self: Counter, initial: t.CInt) -> t.CInt: pass + def increment(self: Counter) -> t.CInt: pass + def get_value(self: Counter) -> t.CInt: pass class StackObj(t.Object): data: t.CInt next_ptr: t.CVoid | t.CPtr -def TestBasicDataClass() -> t.CVoid | t.State: pass +def TestBasicDataClass() -> t.CInt: pass -def TestPoint3DClass() -> t.CVoid | t.State: pass +def TestPoint3DClass() -> t.CInt: pass -def TestStudentClass() -> t.CVoid | t.State: pass +def TestStudentClass() -> t.CInt: pass -def TestCounterClass() -> t.CVoid | t.State: pass +def TestCounterClass() -> t.CInt: pass -def TestStackAllocation() -> t.CVoid | t.State: pass +def TestStackAllocation() -> t.CInt: pass -def TestHeapAllocation() -> t.CVoid | t.State: pass +def TestHeapAllocation() -> t.CInt: pass -def TestHeapObjectWithInit() -> t.CVoid | t.State: pass +def TestHeapObjectWithInit() -> t.CInt: pass -def TestMultipleStackObjects() -> t.CVoid | t.State: pass +def TestMultipleStackObjects() -> t.CInt: pass -def TestImplicitInitCall() -> t.CVoid | t.State: pass +def TestImplicitInitCall() -> t.CInt: pass -def TestClassWithBitFields() -> t.CVoid | t.State: pass +def TestClassWithBitFields() -> t.CInt: pass -def TestIntArray() -> t.CVoid | t.State: pass +def TestIntArray() -> t.CInt: pass -def TestFloatArray() -> t.CVoid | t.State: pass +def TestFloatArray() -> t.CInt: pass -def TestCharArray() -> t.CVoid | t.State: pass +def TestCharArray() -> t.CInt: pass -def TestNestedArray() -> t.CVoid | t.State: pass +def TestNestedArray() -> t.CInt: pass -def TestArrayWithStruct() -> t.CVoid | t.State: pass +def TestArrayWithStruct() -> t.CInt: pass -def TestArrayPointer() -> t.CVoid | t.State: pass +def TestArrayPointer() -> t.CInt: pass -def TestDynamicString() -> t.CVoid | t.State: pass +def TestDynamicString() -> t.CInt: pass diff --git a/Test/TestProject2/temp/faec3233d98371da.pyi b/Test/TestProject2/temp/faec3233d98371da.pyi index 82fcbb8..308f5cb 100644 --- a/Test/TestProject2/temp/faec3233d98371da.pyi +++ b/Test/TestProject2/temp/faec3233d98371da.pyi @@ -7,48 +7,48 @@ Module: zc.logic_test import config import t, c -def ForRangeBasicTest(stop: t.CInt) -> t.CVoid | t.State: pass +def ForRangeBasicTest(stop: t.CInt) -> t.CInt: pass -def ForRangeWithStartStop(start: t.CInt, stop: t.CInt, step: t.CInt) -> t.CVoid | t.State: pass +def ForRangeWithStartStop(start: t.CInt, stop: t.CInt, step: t.CInt) -> t.CInt: pass -def NestedForRangeTest(rows: t.CInt, cols: t.CInt) -> t.CVoid | t.State: pass +def NestedForRangeTest(rows: t.CInt, cols: t.CInt) -> t.CInt: pass -def ForWithIfBreakTest(data_size: t.CInt) -> t.CVoid | t.State: pass +def ForWithIfBreakTest(data_size: t.CInt) -> t.CInt: pass -def ForWithIfContinueTest(n: t.CInt) -> t.CVoid | t.State: pass +def ForWithIfContinueTest(n: t.CInt) -> t.CInt: pass -def ForWithElifBranchTest(value: t.CInt) -> t.CVoid | t.State: pass +def ForWithElifBranchTest(value: t.CInt) -> t.CInt: pass -def WhileWithIfElifElseTest(iterations: t.CInt) -> t.CVoid | t.State: pass +def WhileWithIfElifElseTest(iterations: t.CInt) -> t.CInt: pass -def WhileWithNestedIfTest(limit: t.CInt) -> t.CVoid | t.State: pass +def WhileWithNestedIfTest(limit: t.CInt) -> t.CInt: pass -def WhileWithMatchCaseTest(value: t.CInt) -> t.CVoid | t.State: pass +def WhileWithMatchCaseTest(value: t.CInt) -> t.CInt: pass -def WhileWithMatchCaseNoBreakTest(value: t.CInt) -> t.CVoid | t.State: pass +def WhileWithMatchCaseNoBreakTest(value: t.CInt) -> t.CInt: pass -def ComplexForWhileMatchTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CVoid | t.State: pass +def ComplexForWhileMatchTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CInt: pass -def ForWithCaseAndNoBreakTest(n: t.CInt) -> t.CVoid | t.State: pass +def ForWithCaseAndNoBreakTest(n: t.CInt) -> t.CInt: pass -def WhileWithBreakConditionTest(limit: t.CInt) -> t.CVoid | t.State: pass +def WhileWithBreakConditionTest(limit: t.CInt) -> t.CInt: pass -def NestedWhileWithMultipleBreakPoints(depth: t.CInt, width: t.CInt) -> t.CVoid | t.State: pass +def NestedWhileWithMultipleBreakPoints(depth: t.CInt, width: t.CInt) -> t.CInt: pass -def ForWithMatchCaseInLoopTest(iterations: t.CInt) -> t.CVoid | t.State: pass +def ForWithMatchCaseInLoopTest(iterations: t.CInt) -> t.CInt: pass -def ComplexLogicWithElifChains(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CVoid | t.State: pass +def ComplexLogicWithElifChains(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CInt: pass -def ForRangeWithStepAndCondition(n: t.CInt, step: t.CInt) -> t.CVoid | t.State: pass +def ForRangeWithStepAndCondition(n: t.CInt, step: t.CInt) -> t.CInt: pass -def MatchCaseWithGuardConditions(value: t.CInt) -> t.CVoid | t.State: pass +def MatchCaseWithGuardConditions(value: t.CInt) -> t.CInt: pass -def WhileWithMultipleMatchCases(iterations: t.CInt) -> t.CVoid | t.State: pass +def WhileWithMultipleMatchCases(iterations: t.CInt) -> t.CInt: pass -def ForWhileMixWithBreakAndContinue(n: t.CInt) -> t.CVoid | t.State: pass +def ForWhileMixWithBreakAndContinue(n: t.CInt) -> t.CInt: pass -def ComplexCaseMatchingWithRanges(start: t.CInt, end: t.CInt) -> t.CVoid | t.State: pass +def ComplexCaseMatchingWithRanges(start: t.CInt, end: t.CInt) -> t.CInt: pass -def WhileWithElifInElifChain(limit: t.CInt) -> t.CVoid | t.State: pass +def WhileWithElifInElifChain(limit: t.CInt) -> t.CInt: pass -def ForWithCaseNoBreakNested(inner_limit: t.CInt) -> t.CVoid | t.State: pass +def ForWithCaseNoBreakNested(inner_limit: t.CInt) -> t.CInt: pass diff --git a/Test/TestProject3/output/067c78e9f121dce3.deps.json b/Test/TestProject3/output/067c78e9f121dce3.deps.json index 9ea60d1..f7c4d17 100644 --- a/Test/TestProject3/output/067c78e9f121dce3.deps.json +++ b/Test/TestProject3/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestProject3/output/087c910044fab2d2.deps.json b/Test/TestProject3/output/087c910044fab2d2.deps.json deleted file mode 100644 index 52493aa..0000000 --- a/Test/TestProject3/output/087c910044fab2d2.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/0f4d14c17bf75b10.deps.json b/Test/TestProject3/output/0f4d14c17bf75b10.deps.json index 92bc69f..f95c08f 100644 --- a/Test/TestProject3/output/0f4d14c17bf75b10.deps.json +++ b/Test/TestProject3/output/0f4d14c17bf75b10.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/1b58766d38d05de3.deps.json b/Test/TestProject3/output/1b58766d38d05de3.deps.json index 575d1e0..385a702 100644 --- a/Test/TestProject3/output/1b58766d38d05de3.deps.json +++ b/Test/TestProject3/output/1b58766d38d05de3.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/21ffad37f6fc3fcf.deps.json b/Test/TestProject3/output/21ffad37f6fc3fcf.deps.json deleted file mode 100644 index 16e2398..0000000 --- a/Test/TestProject3/output/21ffad37f6fc3fcf.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/2953a7db4185005b.deps.json b/Test/TestProject3/output/2953a7db4185005b.deps.json new file mode 100644 index 0000000..26eaaa8 --- /dev/null +++ b/Test/TestProject3/output/2953a7db4185005b.deps.json @@ -0,0 +1 @@ +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/29813d57621099a9.deps.json b/Test/TestProject3/output/29813d57621099a9.deps.json index 9ea60d1..dd5f0cf 100644 --- a/Test/TestProject3/output/29813d57621099a9.deps.json +++ b/Test/TestProject3/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json b/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json index 5b6a8ca..26eaaa8 100644 --- a/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json +++ b/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/4d342c40331fc964.deps.json b/Test/TestProject3/output/4d342c40331fc964.deps.json deleted file mode 100644 index 20b6925..0000000 --- a/Test/TestProject3/output/4d342c40331fc964.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/5325ec533a59d71b.deps.json b/Test/TestProject3/output/5325ec533a59d71b.deps.json index b780a03..74a9d28 100644 --- a/Test/TestProject3/output/5325ec533a59d71b.deps.json +++ b/Test/TestProject3/output/5325ec533a59d71b.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/5a6a2137958c28c5.deps.json b/Test/TestProject3/output/5a6a2137958c28c5.deps.json index 79af064..26eaaa8 100644 --- a/Test/TestProject3/output/5a6a2137958c28c5.deps.json +++ b/Test/TestProject3/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/64ac83614c9bdbc6.deps.json b/Test/TestProject3/output/64ac83614c9bdbc6.deps.json index 7784b27..5d84cc9 100644 --- a/Test/TestProject3/output/64ac83614c9bdbc6.deps.json +++ b/Test/TestProject3/output/64ac83614c9bdbc6.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/68c4fe4b12c908e3.deps.json b/Test/TestProject3/output/68c4fe4b12c908e3.deps.json new file mode 100644 index 0000000..26eaaa8 --- /dev/null +++ b/Test/TestProject3/output/68c4fe4b12c908e3.deps.json @@ -0,0 +1 @@ +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json b/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..26eaaa8 --- /dev/null +++ b/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json b/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json index 9ea60d1..40e3886 100644 --- a/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestProject3/output/a326a52b7c4bd6f0.deps.json b/Test/TestProject3/output/a326a52b7c4bd6f0.deps.json deleted file mode 100644 index ab3e82e..0000000 --- a/Test/TestProject3/output/a326a52b7c4bd6f0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/abf9ce3160c9279e.deps.json b/Test/TestProject3/output/abf9ce3160c9279e.deps.json index 7908c78..26eaaa8 100644 --- a/Test/TestProject3/output/abf9ce3160c9279e.deps.json +++ b/Test/TestProject3/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json index ed5f7b3..26eaaa8 100644 --- a/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/c01b27dbcd683245.deps.json b/Test/TestProject3/output/c01b27dbcd683245.deps.json new file mode 100644 index 0000000..1f541f6 --- /dev/null +++ b/Test/TestProject3/output/c01b27dbcd683245.deps.json @@ -0,0 +1 @@ +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json b/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json index f4b825d..26eaaa8 100644 --- a/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/fa3691e66b426950.deps.json b/Test/TestProject3/output/fa3691e66b426950.deps.json index def18b9..26eaaa8 100644 --- a/Test/TestProject3/output/fa3691e66b426950.deps.json +++ b/Test/TestProject3/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/fc49f6314bad25e9.deps.json b/Test/TestProject3/output/fc49f6314bad25e9.deps.json index 250a982..da3fd87 100644 --- a/Test/TestProject3/output/fc49f6314bad25e9.deps.json +++ b/Test/TestProject3/output/fc49f6314bad25e9.deps.json @@ -1 +1 @@ -{"fileiotest": "087c910044fab2d2", "main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "mpool": "21ffad37f6fc3fcf", "vector": "3fdd11bdd589aa8c", "viperlib": "4d342c40331fc964", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "string": "a326a52b7c4bd6f0", "stdlib": "a96738831f025829", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject3/temp/067c78e9f121dce3.pyi b/Test/TestProject3/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/TestProject3/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/TestProject3/temp/0f4d14c17bf75b10.pyi b/Test/TestProject3/temp/0f4d14c17bf75b10.pyi index 46261cb..c414a8b 100644 --- a/Test/TestProject3/temp/0f4d14c17bf75b10.pyi +++ b/Test/TestProject3/temp/0f4d14c17bf75b10.pyi @@ -30,36 +30,36 @@ def double_add[T](a: T, b: T) -> T: pass class A[T]: - def __init__(self: A, a: T) -> t.CVoid: pass + def __init__(self: A, a: T) -> t.CInt: pass def get_a(self: A) -> T: pass class Pair[T1, T2]: - def __init__(self: Pair, first: T1, second: T2) -> t.CVoid: pass + def __init__(self: Pair, first: T1, second: T2) -> t.CInt: pass def get_first(self: Pair) -> T1: pass def get_second(self: Pair) -> T2: pass class Calculator[T]: - def __init__(self: Calculator, init_val: T) -> t.CVoid: pass + def __init__(self: Calculator, init_val: T) -> t.CInt: pass def compute(self: Calculator, other: T) -> T: pass def double_compute(self: Calculator, other: T) -> T: pass class Container[T]: - def __init__(self: Container, v: T) -> t.CVoid: pass + def __init__(self: Container, v: T) -> t.CInt: pass def get_value(self: Container) -> T: pass def get_flag(self: Container) -> CInt32T: pass @t.CVTable class Shape: - def __init__(self: Shape, x: CFloat64T, y: CFloat64T) -> t.CVoid: pass + def __init__(self: Shape, x: CFloat64T, y: CFloat64T) -> t.CInt: pass def area(self: Shape) -> CFloat64T: pass def perimeter(self: Shape) -> CFloat64T: pass def describe(self: Shape) -> CFloat64T: pass @t.CVTable class Circle(Shape): - def __init__(self: Circle, x: CFloat64T, y: CFloat64T, r: CFloat64T) -> t.CVoid: pass + def __init__(self: Circle, x: CFloat64T, y: CFloat64T, r: CFloat64T) -> t.CInt: pass def area(self: Circle) -> CFloat64T: pass def perimeter(self: Circle) -> CFloat64T: pass def scale(self: Circle, factor: CFloat64T) -> 'Circle' | CPtr: pass def move(self: Circle, dx: CFloat64T, dy: CFloat64T) -> 'Circle' | CPtr: pass @t.CVTable class Rect(Shape): - def __init__(self: Rect, x: CFloat64T, y: CFloat64T, w: CFloat64T, h: CFloat64T) -> t.CVoid: pass + def __init__(self: Rect, x: CFloat64T, y: CFloat64T, w: CFloat64T, h: CFloat64T) -> t.CInt: pass def area(self: Rect) -> CFloat64T: pass def perimeter(self: Rect) -> CFloat64T: pass def scale(self: Rect, factor: CFloat64T) -> 'Rect' | CPtr: pass @@ -67,7 +67,7 @@ class Vec2: x: CFloat64T y: CFloat64T def __new__() -> 'Vec2' | CPtr: pass - def __init__(self: Vec2, x: CFloat64T, y: CFloat64T) -> t.CVoid: pass + def __init__(self: Vec2, x: CFloat64T, y: CFloat64T) -> t.CInt: pass def __add__(self: Vec2, b: 'Vec2' | CPtr) -> 'Vec2' | CPtr: pass def __sub__(self: Vec2, b: 'Vec2' | CPtr) -> 'Vec2' | CPtr: pass def __mul__(self: Vec2, s: CFloat64T) -> 'Vec2' | CPtr: pass @@ -79,7 +79,7 @@ class Vec3: y: CFloat64T z: CFloat64T def __new__() -> 'Vec3' | CPtr: pass - def __init__(self: Vec3, x: CFloat64T, y: CFloat64T, z: CFloat64T) -> t.CVoid: pass + def __init__(self: Vec3, x: CFloat64T, y: CFloat64T, z: CFloat64T) -> t.CInt: pass def __add__(self: Vec3, b: 'Vec3' | CPtr) -> 'Vec3' | CPtr: pass def __sub__(self: Vec3, b: 'Vec3' | CPtr) -> 'Vec3' | CPtr: pass def __mul__(self: Vec3, s: CFloat64T) -> 'Vec3' | CPtr: pass @@ -89,14 +89,14 @@ class Vec3: def len_sq(self: Vec3) -> CFloat64T: pass @t.CVTable class Dog: - def __init__(self: Dog, name_val: CInt, bark_power: CInt32T) -> t.CVoid: pass + def __init__(self: Dog, name_val: CInt, bark_power: CInt32T) -> t.CInt: pass def speak(self: Dog) -> CInt: pass def bite(self: Dog) -> CInt32T: pass def take_damage(self: Dog, dmg: CInt32T) -> 'Dog' | CPtr: pass def is_alive(self: Dog) -> CInt: pass @t.CVTable class Cat: - def __init__(self: Cat, name_val: CInt, lives: CInt32T) -> t.CVoid: pass + def __init__(self: Cat, name_val: CInt, lives: CInt32T) -> t.CInt: pass def speak(self: Cat) -> CInt: pass def scratch(self: Cat) -> CInt32T: pass def take_damage(self: Cat, dmg: CInt32T) -> 'Cat' | CPtr: pass @@ -109,22 +109,22 @@ class Transform: scale_y: CFloat64T scale_z: CFloat64T def __new__() -> 'Transform' | CPtr: pass - def __init__(self: Transform, px: CFloat64T, py: CFloat64T, pz: CFloat64T) -> t.CVoid: pass + def __init__(self: Transform, px: CFloat64T, py: CFloat64T, pz: CFloat64T) -> t.CInt: pass def apply_scale(self: Transform, sx: CFloat64T, sy: CFloat64T, sz: CFloat64T) -> 'Transform' | CPtr: pass def world_position(self: Transform) -> 'Vec3' | CPtr: pass @t.CVTable class Vehicle: - def __init__(self: Vehicle, speed: CInt32T) -> t.CVoid: pass + def __init__(self: Vehicle, speed: CInt32T) -> t.CInt: pass def move(self: Vehicle) -> CInt: pass def is_running(self: Vehicle) -> CInt: pass @t.CVTable class Car(Vehicle): - def __init__(self: Car, speed: CInt32T, doors: CInt32T) -> t.CVoid: pass + def __init__(self: Car, speed: CInt32T, doors: CInt32T) -> t.CInt: pass def honk(self: Car) -> CInt: pass @t.CVTable class ElectricCar(Car): - def __init__(self: ElectricCar, speed: CInt32T, doors: CInt32T, battery: CInt32T) -> t.CVoid: pass - def charge(self: ElectricCar) -> t.CVoid: pass + def __init__(self: ElectricCar, speed: CInt32T, doors: CInt32T, battery: CInt32T) -> t.CInt: pass + def charge(self: ElectricCar) -> t.CInt: pass def move(self: ElectricCar) -> CInt: pass def main() -> CInt | CExport: pass diff --git a/Test/CPythonTest/temp/4d342c40331fc964.pyi b/Test/TestProject3/temp/2953a7db4185005b.pyi similarity index 100% rename from Test/CPythonTest/temp/4d342c40331fc964.pyi rename to Test/TestProject3/temp/2953a7db4185005b.pyi diff --git a/Test/TestProject3/temp/29813d57621099a9.pyi b/Test/TestProject3/temp/29813d57621099a9.pyi new file mode 100644 index 0000000..a5e9923 --- /dev/null +++ b/Test/TestProject3/temp/29813d57621099a9.pyi @@ -0,0 +1,85 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass diff --git a/Test/TestProject3/temp/3fdd11bdd589aa8c.pyi b/Test/TestProject3/temp/3fdd11bdd589aa8c.pyi index 4062ae4..de3fa77 100644 --- a/Test/TestProject3/temp/3fdd11bdd589aa8c.pyi +++ b/Test/TestProject3/temp/3fdd11bdd589aa8c.pyi @@ -14,11 +14,11 @@ class Vector[T]: capacity: t.CSizeT elem_size: t.CSizeT pool: mpool.MPool | t.CPtr - def __init__(self: Vector, pool: mpool.MPool | t.CPtr, capacity: t.CSizeT, _hint: T) -> t.CVoid: pass - def push(self: Vector, value: T) -> t.CVoid: pass - def _grow(self: Vector) -> t.CVoid: pass + def __init__(self: Vector, pool: mpool.MPool | t.CPtr, capacity: t.CSizeT, _hint: T) -> t.CInt: pass + def push(self: Vector, value: T) -> t.CInt: pass + def _grow(self: Vector) -> t.CInt: pass def get(self: Vector, index: t.CSizeT) -> T: pass - def set(self: Vector, index: t.CSizeT, value: T) -> t.CVoid: pass + def set(self: Vector, index: t.CSizeT, value: T) -> t.CInt: pass def len(self: Vector) -> t.CSizeT: pass - def clear(self: Vector) -> t.CVoid: pass - def free(self: Vector) -> t.CVoid: pass \ No newline at end of file + def clear(self: Vector) -> t.CInt: pass + def free(self: Vector) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject3/temp/4d342c40331fc964.pyi b/Test/TestProject3/temp/4d342c40331fc964.pyi deleted file mode 100644 index aa40bc7..0000000 --- a/Test/TestProject3/temp/4d342c40331fc964.pyi +++ /dev/null @@ -1,19 +0,0 @@ -""" -Auto-generated Python stub file from viperlib.py -Module: viperlib -""" - - -import t, c -import viperio -from stdarg import arg - -TEMP_BUF_SIZE: t.CDefine = 24 - -def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt | t.State: pass - -def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.State: pass - -def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt | t.State: pass - -def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.State: pass diff --git a/Test/TestProject3/temp/68c4fe4b12c908e3.pyi b/Test/TestProject3/temp/68c4fe4b12c908e3.pyi new file mode 100644 index 0000000..fc2010b --- /dev/null +++ b/Test/TestProject3/temp/68c4fe4b12c908e3.pyi @@ -0,0 +1,50 @@ +""" +Auto-generated Python stub file from mpool.py +Module: mpool +""" + + +import t, c +from stdint import * +import viperio +import string + +MPOOL_ALIGN: t.CDefine = 8 +MPOOL_TYPE_SLAB: t.CDefine = 0 +MPOOL_TYPE_BUMP: t.CDefine = 2 + +def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass + + +class MPool: + mtype: t.CInt + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + offset: t.CSizeT + high_water: t.CSizeT + block_size: t.CSizeT + block_count: t.CSizeT + used_count: t.CSizeT + free_list: t.CVoid | t.CPtr + alloc_map: t.CUInt8T | t.CPtr + alloc_map_size: t.CSizeT + def __init__(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass + def _init_bump(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> t.CInt: pass + def _init_slab(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MPool) -> 'MPool' | t.CPtr: pass + def __exit__(self: MPool) -> t.CInt: pass + def _slab_reset(self: MPool) -> t.CInt: pass + def alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def alloc_buf(self: MPool, capacity: t.CSizeT) -> viperio.Buf | t.CPtr: pass + def free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def realloc(self: MPool, ptr: t.CVoid | t.CPtr, old_size: t.CSizeT, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def reset(self: MPool) -> t.CInt: pass + def _bump_alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def _slab_alloc(self: MPool) -> t.CVoid | t.CPtr: pass + def _slab_free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + +def bump_create(mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> MPool | t.CPtr: pass + +def alloc(pool: MPool | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def reset(pool: MPool | t.CPtr) -> t.CInt: pass diff --git a/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi b/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TestProject3/temp/6c2029b306556c00.pyi b/Test/TestProject3/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/TestProject3/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/TestProject3/temp/72e2d5ccb7cedcf1.pyi b/Test/TestProject3/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/TestProject3/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/TestProject3/temp/_sha1_map.txt b/Test/TestProject3/temp/_sha1_map.txt index f36c421..5672ef4 100644 --- a/Test/TestProject3/temp/_sha1_map.txt +++ b/Test/TestProject3/temp/_sha1_map.txt @@ -1,19 +1,19 @@ -087c910044fab2d2:fileiotest.py 0f4d14c17bf75b10:main.py 1b58766d38d05de3:enumtest.py -21ffad37f6fc3fcf:includes/mpool.py +2953a7db4185005b:includes/viperlib.py 3fdd11bdd589aa8c:includes/vector.py -4d342c40331fc964:includes/viperlib.py 5325ec533a59d71b:mpooltest.py 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py 64ac83614c9bdbc6:definetest.py +68c4fe4b12c908e3:includes/mpool.py +6aee24fdefa3cbc0:includes/string.py +6c2029b306556c00:includes/stdlib.py 71e0a3ffcb3ebfad:includes/stdarg.py 93c1d18e35d188d6:includes/platmacro.py -a326a52b7c4bd6f0:includes/string.py -a96738831f025829:includes/stdlib.py abf9ce3160c9279e:includes/w32\win32file.py bbdf3bbd4c3bc28c:includes/w32\win32console.py +c01b27dbcd683245:fileiotest.py c9f4be41ca1cc2b4:includes/viperio.py fa3691e66b426950:includes/w32\fileio.py fc49f6314bad25e9:vectortest.py diff --git a/Test/TestProject3/temp/_shared_sym.pkl b/Test/TestProject3/temp/_shared_sym.pkl index 0a14880..726a0e1 100644 Binary files a/Test/TestProject3/temp/_shared_sym.pkl and b/Test/TestProject3/temp/_shared_sym.pkl differ diff --git a/Test/TestProject3/temp/a326a52b7c4bd6f0.pyi b/Test/TestProject3/temp/a326a52b7c4bd6f0.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/TestProject3/temp/a326a52b7c4bd6f0.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TestProject3/temp/a96738831f025829.pyi b/Test/TestProject3/temp/a96738831f025829.pyi deleted file mode 100644 index c499547..0000000 --- a/Test/TestProject3/temp/a96738831f025829.pyi +++ /dev/null @@ -1,16 +0,0 @@ -""" -Auto-generated Python stub file from stdlib.py -Module: stdlib -""" - -import c - - -from stdint import * -import t - -def malloc(size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def realloc(p: str, p2: t.CLong | t.CLong) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/TestProject3/temp/087c910044fab2d2.pyi b/Test/TestProject3/temp/c01b27dbcd683245.pyi similarity index 62% rename from Test/TestProject3/temp/087c910044fab2d2.pyi rename to Test/TestProject3/temp/c01b27dbcd683245.pyi index b7d60d2..fdb53f8 100644 --- a/Test/TestProject3/temp/087c910044fab2d2.pyi +++ b/Test/TestProject3/temp/c01b27dbcd683245.pyi @@ -17,14 +17,14 @@ from w32.fileio import File, FileW, MODE, FRESULT, SEEK_SET, SEEK_CUR, SEEK_END BUF_SIZE: t.CDefine = 4096 -def fileio_main() -> t.CVoid: pass +def fileio_main() -> t.CInt: pass -def fileio_with_test() -> t.CVoid: pass +def fileio_with_test() -> t.CInt: pass -def fileio_handle_test() -> t.CVoid: pass +def fileio_handle_test() -> t.CInt: pass -def fileio_rw_test() -> t.CVoid: pass +def fileio_rw_test() -> t.CInt: pass -def fileio_wide_test() -> t.CVoid: pass +def fileio_wide_test() -> t.CInt: pass -def fileio_chinese_test() -> t.CVoid: pass +def fileio_chinese_test() -> t.CInt: pass diff --git a/Test/TestProject3/temp/c9f4be41ca1cc2b4.pyi b/Test/TestProject3/temp/c9f4be41ca1cc2b4.pyi index 2c2291b..fdbd7ec 100644 --- a/Test/TestProject3/temp/c9f4be41ca1cc2b4.pyi +++ b/Test/TestProject3/temp/c9f4be41ca1cc2b4.pyi @@ -12,11 +12,11 @@ class Buf: length: t.CSizeT capacity: t.CSizeT owned: bool - def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CVoid: pass - def clear(self: Buf) -> t.CVoid: pass + def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass + def clear(self: Buf) -> t.CInt: pass def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass def cstr(self: Buf) -> t.CChar | t.CPtr: pass - def reset(self: Buf) -> t.CVoid: pass + def reset(self: Buf) -> t.CInt: pass def __enter__(self: Buf) -> 'Buf' | t.CPtr: pass - def __exit__(self: Buf) -> t.CVoid: pass - def free(self: Buf) -> t.CVoid: pass \ No newline at end of file + def __exit__(self: Buf) -> t.CInt: pass + def free(self: Buf) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject3/temp/fa3691e66b426950.pyi b/Test/TestProject3/temp/fa3691e66b426950.pyi index 109c920..48fd36c 100644 --- a/Test/TestProject3/temp/fa3691e66b426950.pyi +++ b/Test/TestProject3/temp/fa3691e66b426950.pyi @@ -41,9 +41,9 @@ class File: can_write: bool is_append: bool _share_mode: ULONG - def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CVoid: pass + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass def __enter__(self: File) -> 'File' | t.CPtr: pass - def __exit__(self: File) -> t.CVoid: pass + def __exit__(self: File) -> t.CInt: pass def read(self: File, buf: bytes, count: ULONG) -> LONG: pass def write(self: File, buf: bytes, count: ULONG) -> LONG: pass def write_str(self: File, s: str) -> LONG: pass @@ -61,9 +61,9 @@ class FileW: can_write: bool is_append: bool _share_mode: ULONG - def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CVoid: pass + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass - def __exit__(self: FileW) -> t.CVoid: pass + def __exit__(self: FileW) -> t.CInt: pass def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass def write_str(self: FileW, s: str) -> LONG: pass diff --git a/Test/TypeCastTest/output/067c78e9f121dce3.deps.json b/Test/TypeCastTest/output/067c78e9f121dce3.deps.json index 52b8465..cd8312a 100644 --- a/Test/TypeCastTest/output/067c78e9f121dce3.deps.json +++ b/Test/TypeCastTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/29813d57621099a9.deps.json b/Test/TypeCastTest/output/29813d57621099a9.deps.json index 4159704..0e31226 100644 --- a/Test/TypeCastTest/output/29813d57621099a9.deps.json +++ b/Test/TypeCastTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json b/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json index a9f1746..276387f 100644 --- a/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json +++ b/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json b/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..5cd9b08 --- /dev/null +++ b/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json b/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json index 1340dfa..00aa2be 100644 --- a/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/a326a52b7c4bd6f0.deps.json b/Test/TypeCastTest/output/a326a52b7c4bd6f0.deps.json deleted file mode 100644 index d9c58a4..0000000 --- a/Test/TypeCastTest/output/a326a52b7c4bd6f0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json b/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json index 1340dfa..00aa2be 100644 --- a/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json +++ b/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json index a9f1746..276387f 100644 --- a/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/bf230611b27080fa.deps.json b/Test/TypeCastTest/output/bf230611b27080fa.deps.json index 73440e6..2fc9271 100644 --- a/Test/TypeCastTest/output/bf230611b27080fa.deps.json +++ b/Test/TypeCastTest/output/bf230611b27080fa.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/fa3691e66b426950.deps.json b/Test/TypeCastTest/output/fa3691e66b426950.deps.json index a9f1746..276387f 100644 --- a/Test/TypeCastTest/output/fa3691e66b426950.deps.json +++ b/Test/TypeCastTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "string": "a326a52b7c4bd6f0", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi b/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TypeCastTest/temp/_sha1_map.txt b/Test/TypeCastTest/temp/_sha1_map.txt index 3de0bca..0c48640 100644 --- a/Test/TypeCastTest/temp/_sha1_map.txt +++ b/Test/TypeCastTest/temp/_sha1_map.txt @@ -1,7 +1,7 @@ 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -a326a52b7c4bd6f0:includes/string.py bbdf3bbd4c3bc28c:includes/w32\win32console.py bf230611b27080fa:main.py diff --git a/Test/TypeCastTest/temp/a326a52b7c4bd6f0.pyi b/Test/TypeCastTest/temp/a326a52b7c4bd6f0.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/TypeCastTest/temp/a326a52b7c4bd6f0.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/VariadicTest/output/067c78e9f121dce3.deps.json b/Test/VariadicTest/output/067c78e9f121dce3.deps.json index 47eefe1..c11e2c3 100644 --- a/Test/VariadicTest/output/067c78e9f121dce3.deps.json +++ b/Test/VariadicTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/VariadicTest/output/2953a7db4185005b.deps.json b/Test/VariadicTest/output/2953a7db4185005b.deps.json index ffc1ba9..43983e1 100644 --- a/Test/VariadicTest/output/2953a7db4185005b.deps.json +++ b/Test/VariadicTest/output/2953a7db4185005b.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/29813d57621099a9.deps.json b/Test/VariadicTest/output/29813d57621099a9.deps.json index ffc1ba9..abec65b 100644 --- a/Test/VariadicTest/output/29813d57621099a9.deps.json +++ b/Test/VariadicTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/VariadicTest/output/377ad03e9b90ac39.deps.json b/Test/VariadicTest/output/377ad03e9b90ac39.deps.json index affbd7f..2839e14 100644 --- a/Test/VariadicTest/output/377ad03e9b90ac39.deps.json +++ b/Test/VariadicTest/output/377ad03e9b90ac39.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/5a6a2137958c28c5.deps.json b/Test/VariadicTest/output/5a6a2137958c28c5.deps.json index 592b804..791ea77 100644 --- a/Test/VariadicTest/output/5a6a2137958c28c5.deps.json +++ b/Test/VariadicTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/VariadicTest/output/4d5db7f970ef510f.deps.json b/Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json similarity index 64% rename from Test/VariadicTest/output/4d5db7f970ef510f.deps.json rename to Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json index 6adc4cf..43983e1 100644 --- a/Test/VariadicTest/output/4d5db7f970ef510f.deps.json +++ b/Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json b/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json index a8ad265..e515c67 100644 --- a/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/VariadicTest/output/abf9ce3160c9279e.deps.json b/Test/VariadicTest/output/abf9ce3160c9279e.deps.json index 77b9eb5..dbd0c83 100644 --- a/Test/VariadicTest/output/abf9ce3160c9279e.deps.json +++ b/Test/VariadicTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json index 592b804..791ea77 100644 --- a/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json b/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json index 6adc4cf..43983e1 100644 --- a/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/fa3691e66b426950.deps.json b/Test/VariadicTest/output/fa3691e66b426950.deps.json index 592b804..791ea77 100644 --- a/Test/VariadicTest/output/fa3691e66b426950.deps.json +++ b/Test/VariadicTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "string": "4d5db7f970ef510f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/VariadicTest/temp/4d5db7f970ef510f.pyi b/Test/VariadicTest/temp/4d5db7f970ef510f.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/VariadicTest/temp/4d5db7f970ef510f.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi b/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/VariadicTest/temp/_sha1_map.txt b/Test/VariadicTest/temp/_sha1_map.txt index d9d969b..318fb4b 100644 --- a/Test/VariadicTest/temp/_sha1_map.txt +++ b/Test/VariadicTest/temp/_sha1_map.txt @@ -1,8 +1,8 @@ 2953a7db4185005b:includes/viperlib.py 377ad03e9b90ac39:main.py -4d5db7f970ef510f:includes/string.py 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py 71e0a3ffcb3ebfad:includes/stdarg.py 73edbcf76e32d00b:includes/stdio.py bbdf3bbd4c3bc28c:includes/w32\win32console.py diff --git a/Test/ZlibTest/App/__zlib/test_pyzlib.py b/Test/ZlibTest/App/__zlib/test_pyzlib.py index 256df64..d3b5b89 100644 --- a/Test/ZlibTest/App/__zlib/test_pyzlib.py +++ b/Test/ZlibTest/App/__zlib/test_pyzlib.py @@ -331,7 +331,7 @@ def test_compress_copy(): c1.compress(BYTEPTR(inp), input_length, c.Addr(out_length)) printf(" Original: compressed %zu bytes so far\n", out_length) - c2: pyzlib.Compress = c1.copy() + c2: pyzlib.Compress | t.CPtr = c1.copy() check("compress copy OK", c2 != None, "copy returned None") printf(" Copied compressobj\n") @@ -524,7 +524,7 @@ def test_zdict(): printf(" Input : \"%s\" (%zu bytes)\n", inp, input_length) out_length: t.CSizeT = 0 - s: pyzlib.Compress = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, + s: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, pyzlib.Z_DEFAULT_STRATEGY, BYTEPTR(dict), strlen(dict)) diff --git a/Test/ZlibTest/output/024a3459d0f585ae.deps.json b/Test/ZlibTest/output/024a3459d0f585ae.deps.json deleted file mode 100644 index 98f9df8..0000000 --- a/Test/ZlibTest/output/024a3459d0f585ae.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file diff --git a/Test/ZlibTest/output/067c78e9f121dce3.deps.json b/Test/ZlibTest/output/067c78e9f121dce3.deps.json index 5007e65..02e0914 100644 --- a/Test/ZlibTest/output/067c78e9f121dce3.deps.json +++ b/Test/ZlibTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/ZlibTest/output/0af305ed4e5f787d.deps.json b/Test/ZlibTest/output/0af305ed4e5f787d.deps.json index 536ae4c..b87171f 100644 --- a/Test/ZlibTest/output/0af305ed4e5f787d.deps.json +++ b/Test/ZlibTest/output/0af305ed4e5f787d.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/29813d57621099a9.deps.json b/Test/ZlibTest/output/29813d57621099a9.deps.json index c0a37ee..c0ff589 100644 --- a/Test/ZlibTest/output/29813d57621099a9.deps.json +++ b/Test/ZlibTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/ZlibTest/output/53fa0c913947021f.deps.json b/Test/ZlibTest/output/53fa0c913947021f.deps.json new file mode 100644 index 0000000..b0c8785 --- /dev/null +++ b/Test/ZlibTest/output/53fa0c913947021f.deps.json @@ -0,0 +1 @@ +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/5a6a2137958c28c5.deps.json b/Test/ZlibTest/output/5a6a2137958c28c5.deps.json index 661fe60..f29b4ab 100644 --- a/Test/ZlibTest/output/5a6a2137958c28c5.deps.json +++ b/Test/ZlibTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json b/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json new file mode 100644 index 0000000..6276ce6 --- /dev/null +++ b/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json @@ -0,0 +1 @@ +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json b/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json index 25dc5a3..7138317 100644 --- a/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json b/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json index 7d3127d..e18b0d6 100644 --- a/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json +++ b/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/95e27d852b773ae8.deps.json b/Test/ZlibTest/output/95e27d852b773ae8.deps.json index 365282c..b228098 100644 --- a/Test/ZlibTest/output/95e27d852b773ae8.deps.json +++ b/Test/ZlibTest/output/95e27d852b773ae8.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/abf9ce3160c9279e.deps.json b/Test/ZlibTest/output/abf9ce3160c9279e.deps.json index 25dc5a3..7138317 100644 --- a/Test/ZlibTest/output/abf9ce3160c9279e.deps.json +++ b/Test/ZlibTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json index ac30ccb..39ce516 100644 --- a/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json b/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json index 88b64c9..273dcc1 100644 --- a/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json +++ b/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/dca7ef1d57347738.deps.json b/Test/ZlibTest/output/dca7ef1d57347738.deps.json index bf53f56..6c2e844 100644 --- a/Test/ZlibTest/output/dca7ef1d57347738.deps.json +++ b/Test/ZlibTest/output/dca7ef1d57347738.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json b/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json index 5c0cc0d..8c2e8d1 100644 --- a/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json +++ b/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/f9cd063200178785.deps.json b/Test/ZlibTest/output/f9cd063200178785.deps.json index b3e8265..bc04c95 100644 --- a/Test/ZlibTest/output/f9cd063200178785.deps.json +++ b/Test/ZlibTest/output/f9cd063200178785.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f"} \ No newline at end of file diff --git a/Test/ZlibTest/output/fa3691e66b426950.deps.json b/Test/ZlibTest/output/fa3691e66b426950.deps.json index 661fe60..f29b4ab 100644 --- a/Test/ZlibTest/output/fa3691e66b426950.deps.json +++ b/Test/ZlibTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "__zlib.test_pyzlib": "ffaa1aaa1355e604", "test_pyzlib": "ffaa1aaa1355e604", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/ZlibTest/output/ffaa1aaa1355e604.deps.json b/Test/ZlibTest/output/ffaa1aaa1355e604.deps.json deleted file mode 100644 index 7b7af4a..0000000 --- a/Test/ZlibTest/output/ffaa1aaa1355e604.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"string": "024a3459d0f585ae", "__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "stdlib": "a96738831f025829", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/temp/024a3459d0f585ae.pyi b/Test/ZlibTest/temp/024a3459d0f585ae.pyi deleted file mode 100644 index eae6834..0000000 --- a/Test/ZlibTest/temp/024a3459d0f585ae.pyi +++ /dev/null @@ -1,40 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/ZlibTest/temp/ffaa1aaa1355e604.pyi b/Test/ZlibTest/temp/53fa0c913947021f.pyi similarity index 100% rename from Test/ZlibTest/temp/ffaa1aaa1355e604.pyi rename to Test/ZlibTest/temp/53fa0c913947021f.pyi diff --git a/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi b/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi new file mode 100644 index 0000000..c17475f --- /dev/null +++ b/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/ZlibTest/temp/6c2029b306556c00.pyi b/Test/ZlibTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/ZlibTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/ZlibTest/temp/_sha1_map.txt b/Test/ZlibTest/temp/_sha1_map.txt index 3c10a9e..ec470f2 100644 --- a/Test/ZlibTest/temp/_sha1_map.txt +++ b/Test/ZlibTest/temp/_sha1_map.txt @@ -1,14 +1,14 @@ -024a3459d0f585ae:includes/string.py 0af305ed4e5f787d:__zlib\zdeflate.py +53fa0c913947021f:__zlib\test_pyzlib.py 56cdd754a8a09347:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py +6aee24fdefa3cbc0:includes/string.py +6c2029b306556c00:includes/stdlib.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py 7e9fab9c7b47c4db:__zlib\pyzlib.py 95e27d852b773ae8:__zlib\zchecksum.py -a96738831f025829:includes/stdlib.py c9349bf1e8390dd5:__zlib\zhuff.py dca7ef1d57347738:main.py e00d9854a0d03f4f:__zlib\zinflate.py f9cd063200178785:__zlib\zdef.py -ffaa1aaa1355e604:__zlib\test_pyzlib.py diff --git a/Test/ZlibTest/temp/_shared_sym.pkl b/Test/ZlibTest/temp/_shared_sym.pkl index 87361f3..30cf99f 100644 Binary files a/Test/ZlibTest/temp/_shared_sym.pkl and b/Test/ZlibTest/temp/_shared_sym.pkl differ diff --git a/Test/ZlibTest/temp/a96738831f025829.pyi b/Test/ZlibTest/temp/a96738831f025829.pyi deleted file mode 100644 index c499547..0000000 --- a/Test/ZlibTest/temp/a96738831f025829.pyi +++ /dev/null @@ -1,16 +0,0 @@ -""" -Auto-generated Python stub file from stdlib.py -Module: stdlib -""" - -import c - - -from stdint import * -import t - -def malloc(size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def realloc(p: str, p2: t.CLong | t.CLong) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass - -def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/fbnq_out b/Test/fbnq_out deleted file mode 100644 index 888f849..0000000 --- a/Test/fbnq_out +++ /dev/null @@ -1,676 +0,0 @@ -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='OOPTest2', ctx=Load()), op=BitOr(), righ... -[GetCTypeInfo] Node type: Name, dump: Name(id='OOPTest2', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=At... -[GetCTypeInfo] Node type: Name, dump: Name(id='Item', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CDefine', ct... -[GetCTypeInfo-Attribute] 查询: 'CDefine' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='BigEndian', ... -[GetCTypeInfo-Attribute] 查询: 'BigEndian' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='LittleEndian... -[GetCTypeInfo-Attribute] 查询: 'LittleEndian' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='OOPTest2', ctx=Load()), op=BitOr(), righ... -[GetCTypeInfo] Node type: Name, dump: Name(id='OOPTest2', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='str', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='str', ctx=Load())... -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Name, dump: Name(id='str', ctx=Load())... -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedInt... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=At... -[GetCTypeInfo] Node type: Name, dump: Name(id='Item', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='EnumTest', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt16T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt64T' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='BigEndian', ... -[GetCTypeInfo-Attribute] 查询: 'BigEndian' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='LittleEndian... -[GetCTypeInfo-Attribute] 查询: 'LittleEndian' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedCha... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=At... -[GetCTypeInfo] Node type: Name, dump: Name(id='Item', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt16T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt64T' ModulePath: t -=== AST Tree (Compact) === -Module(body=[ImportFrom(module='stdlib', names=[alias(name='malloc'), alias(name='free')], level=0), Import(names=[alias(name='ctypes')]), ImportFrom(module='stdint', names=[alias(name='*')], level=0), Import(names=[alias(name='string')]), Import(names=[alias(name='w32.win32console')]), ImportFrom(module='stdarg', names=[alias(name='va_start'), alias(name='va_end'), alias(name='va_arg'), alias(name='va_list')], level=0), Import(names=[alias(name='t')]), Import(names=[alias(name='c')]), ClassDef(name='Struct1', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=Name(id='UINT', ctx=Load()), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=Name(id='UINT', ctx=Load()), value=Constant(value=123), simple=1)], decorator_list=[], type_params=[]), AnnAssign(target=Name(id='S1', ctx=Store()), annotation=Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elts=[Name(id='Struct1', ctx=Load()), Constant(value=5)], ctx=Load()), ctx=Load()), value=List(elts=[Call(func=Name(id='Struct1', ctx=Load()), args=[Constant(value=1), Constant(value=2)], keywords=[]), Call(func=Name(id='Struct1', ctx=Load()), args=[], keywords=[keyword(arg='b', value=Constant(value=3)), keyword(arg='a', value=Constant(value=4))]), Call(func=Name(id='Struct1', ctx=Load()), args=[], keywords=[keyword(arg='a', value=Constant(value=5)), keyword(arg='b', value=Constant(value=6))]), Call(func=Name(id='Struct1', ctx=Load()), args=[Constant(value=7)], keywords=[keyword(arg='b', value=Constant(value=8))]), Call(func=Name(id='Struct1', ctx=Load()), args=[Constant(value=9)], keywords=[])], ctx=Load()), simple=1), AnnAssign(target=Name(id='S1_', ctx=Store()), annotation=Name(id='Struct1', ctx=Load()), value=Call(func=Name(id='Struct1', ctx=Load()), args=[Constant(value=10)], keywords=[]), simple=1), Assign(targets=[Name(id='S1_2', ctx=Store())], value=Call(func=Name(id='Struct1', ctx=Load()), args=[Constant(value=112)], keywords=[])), FunctionDef(name='reptr', args=arguments(posonlyargs=[], args=[arg(arg='p', annotation=BinOp(left=Name(id='UINT', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load()))), arg(arg='v', annotation=Name(id='UINT', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='DerefAs', ctx=Load()), args=[Name(id='p', ctx=Load()), Name(id='v', ctx=Load())], keywords=[]))], decorator_list=[], type_params=[]), AnnAssign(target=Name(id='GLOBAL_VAR', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), ClassDef(name='OOPTest2', bases=[], keywords=[], body=[AnnAssign(target=Name(id='fb', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), simple=1), FunctionDef(name='__init__', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='fb', ctx=Store())], value=Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=1024)], keywords=[])), For(target=Name(id='i', ctx=Store()), iter=Call(func=Name(id='range', ctx=Load()), args=[Constant(value=0), Constant(value=1024)], keywords=[]), body=[Assign(targets=[Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='fb', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='1'))], orelse=[]), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='fb', ctx=Load()), slice=Constant(value=1023), ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), Constant(value='\x00')], keywords=[]))], decorator_list=[], type_params=[]), FunctionDef(name='GetFB', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Return(value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Attribute(value=Name(id='self', ctx=Load()), attr='fb', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]))], decorator_list=[], returns=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), type_params=[]), FunctionDef(name='__del__', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='OOPTest2 __del__')], keywords=[])), Expr(value=Call(func=Name(id='free', ctx=Load()), args=[Attribute(value=Name(id='self', ctx=Load()), attr='fb', ctx=Load())], keywords=[]))], decorator_list=[], type_params=[])], decorator_list=[Attribute(value=Name(id='t', ctx=Load()), attr='Object', ctx=Load())], type_params=[]), ClassDef(name='OOPTest', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=Name(id='UINT', ctx=Load()), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=Name(id='UINT', ctx=Load()), value=Constant(value=12345), simple=1), AnnAssign(target=Name(id='c', ctx=Store()), annotation=Name(id='UINT', ctx=Load()), simple=1), AnnAssign(target=Name(id='oop2', ctx=Store()), annotation=BinOp(left=Name(id='OOPTest2', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), simple=1), FunctionDef(name='__init__', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='a', ctx=Store())], value=Constant(value=451)), Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='oop2', ctx=Store())], value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Addr', ctx=Load()), args=[Call(func=Name(id='OOPTest2', ctx=Load()), args=[], keywords=[])], keywords=[])), Assign(targets=[Subscript(value=Call(func=Attribute(value=Attribute(value=Name(id='self', ctx=Load()), attr='oop2', ctx=Load()), attr='GetFB', ctx=Load()), args=[], keywords=[]), slice=Constant(value=0), ctx=Store())], value=Constant(value='1')), Assign(targets=[Name(id='cp', ctx=Store())], value=Attribute(value=Attribute(value=Name(id='self', ctx=Load()), attr='oop2', ctx=Load()), attr='fb', ctx=Load())), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=1), ctx=Store())], value=Constant(value='4')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=2), ctx=Store())], value=Constant(value='5')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=3), ctx=Store())], value=Constant(value='6')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=4), ctx=Store())], value=Constant(value='7')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=5), ctx=Store())], value=Constant(value='8')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=6), ctx=Store())], value=Constant(value='9')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=7), ctx=Store())], value=Constant(value='0')), Assign(targets=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=8), ctx=Store())], value=Constant(value='9')), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=0), ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='长度:'), Call(func=Attribute(value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Name(id='cp', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), attr='__sizeof__', ctx=Load()), args=[], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='cp[0]:'), Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])), AugAssign(target=Name(id='cp', ctx=Store()), op=Add(), value=Constant(value=1)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='cp[0]:'), Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])), AugAssign(target=Name(id='cp', ctx=Store()), op=Add(), value=Constant(value=1)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='self.oop2.GetFB()[0]:'), Call(func=Name(id='int', ctx=Load()), args=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])], keywords=[])), AugAssign(target=Name(id='cp', ctx=Store()), op=Sub(), value=Constant(value=2)), Assign(targets=[Name(id='lambda_a', ctx=Store())], value=Lambda(args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=Constant(value=1))), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Subscript(value=Name(id='cp', ctx=Load()), slice=Constant(value=0), ctx=Load()), Call(func=Name(id='lambda_a', ctx=Load()), args=[], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='type', ctx=Load()), args=[Name(id='cp', ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='dir', ctx=Load()), args=[Name(id='OOPTest2', ctx=Load())], keywords=[])], keywords=[])), AnnAssign(target=Name(id='vkt', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), value=Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=1024)], keywords=[]), simple=1), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Subscript(value=Name(id='vkt', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[]), Constant(value=8080)], keywords=[])), Assign(targets=[Subscript(value=Name(id='vkt', ctx=Load()), slice=Constant(value=0), ctx=Store())], value=Constant(value='2')), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Subscript(value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Subscript(value=Name(id='vkt', ctx=Load()), slice=Constant(value=0), ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), slice=Constant(value=0), ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='type', ctx=Load()), args=[Subscript(value=Name(id='vkt', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), args=[Constant(value='Hello')], keywords=[]), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='str', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Addr', ctx=Load()), args=[Constant(value='你好')], keywords=[])], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='free', ctx=Load()), args=[Name(id='vkt', ctx=Load())], keywords=[])), AnnAssign(target=Name(id='vkt', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), value=Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=1024)], keywords=[]), simple=1), AnnAssign(target=Name(id='vkt2', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Name(id='vkt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), simple=1), Assign(targets=[Subscript(value=Name(id='vkt2', ctx=Load()), slice=Constant(value=0), ctx=Store())], value=Constant(value='1')), Assign(targets=[Subscript(value=Name(id='vkt2', ctx=Load()), slice=Constant(value=100), ctx=Store())], value=Constant(value='1')), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='首个参数:'), Subscript(value=Name(id='vkt2', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='第100参数:'), Subscript(value=Name(id='vkt2', ctx=Load()), slice=Constant(value=100), ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='free', ctx=Load()), args=[Name(id='vkt', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='HEX'), Call(func=Name(id='str_to_hex', ctx=Load()), args=[Constant(value='ABCDEFHIJKLMN')], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='HEX'), Call(func=Name(id='str_to_hex', ctx=Load()), args=[Constant(value='1')], keywords=[])], keywords=[])), Delete(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='oop2', ctx=Del())])], decorator_list=[], type_params=[])], decorator_list=[Attribute(value=Name(id='t', ctx=Load()), attr='Object', ctx=Load())], type_params=[]), FunctionDef(name='str_to_hex', args=arguments(posonlyargs=[], args=[arg(arg='s', annotation=Name(id='str', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[AnnAssign(target=Name(id='buf', ctx=Store()), annotation=Name(id='str', ctx=Load()), value=Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=1024)], keywords=[]), simple=1), AnnAssign(target=Name(id='out', ctx=Store()), annotation=Name(id='str', ctx=Load()), value=Name(id='buf', ctx=Load()), simple=1), AnnAssign(target=Name(id='hex', ctx=Store()), annotation=Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elts=[Name(id='str', ctx=Load()), Constant(value=None)], ctx=Load()), ctx=Load()), value=Constant(value='0123456789ABCDEF'), simple=1), While(test=Compare(left=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Name(id='s', ctx=Load())], keywords=[]), ops=[NotEq()], comparators=[Constant(value=0)]), body=[AnnAssign(target=Name(id='cr', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedChar', ctx=Load()), value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Name(id='s', ctx=Load())], keywords=[]), simple=1), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Name(id='out', ctx=Load())], keywords=[]), Subscript(value=Name(id='hex', ctx=Load()), slice=BinOp(left=BinOp(left=Name(id='cr', ctx=Load()), op=RShift(), right=Constant(value=4)), op=BitAnd(), right=Constant(value=15)), ctx=Load())], keywords=[])), AugAssign(target=Name(id='out', ctx=Store()), op=Add(), value=Constant(value=1)), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Name(id='out', ctx=Load())], keywords=[]), Subscript(value=Name(id='hex', ctx=Load()), slice=BinOp(left=Name(id='cr', ctx=Load()), op=BitAnd(), right=Constant(value=15)), ctx=Load())], keywords=[])), AugAssign(target=Name(id='out', ctx=Store()), op=Add(), value=Constant(value=1)), AugAssign(target=Name(id='s', ctx=Store()), op=Add(), value=Constant(value=1))], orelse=[]), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Name(id='out', ctx=Load())], keywords=[]), Constant(value=0)], keywords=[])), Return(value=Name(id='buf', ctx=Load()))], decorator_list=[], returns=Name(id='str', ctx=Load()), type_params=[]), FunctionDef(name='int_to_hex', args=arguments(posonlyargs=[], args=[arg(arg='num', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Assign(targets=[Name(id='buf', ctx=Store())], value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=128)], keywords=[]), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[])), If(test=UnaryOp(op=Not(), operand=Name(id='buf', ctx=Load())), body=[Return(value=Constant(value=None))], orelse=[]), AnnAssign(target=Name(id='hex_chars', ctx=Store()), annotation=Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elts=[Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), Constant(value=None)], ctx=Load()), ctx=Load()), value=Constant(value='0123456789ABCDEF'), simple=1), Assign(targets=[Name(id='i', ctx=Store())], value=Constant(value=0)), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='0')), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=BinOp(left=Name(id='i', ctx=Load()), op=Add(), right=Constant(value=1)), ctx=Store())], value=Constant(value='x')), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=2)), If(test=Compare(left=Name(id='num', ctx=Load()), ops=[Eq()], comparators=[Constant(value=0)]), body=[Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='0')), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1)), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='0')), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1)), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='\x00')), Return(value=Name(id='buf', ctx=Load()))], orelse=[]), AnnAssign(target=Name(id='temp', ctx=Store()), annotation=Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elts=[Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), Constant(value=32)], ctx=Load()), ctx=Load()), simple=1), Assign(targets=[Name(id='temp_idx', ctx=Store())], value=Constant(value=0)), AnnAssign(target=Name(id='n', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedInt', ctx=Load()), value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedInt', ctx=Load()), args=[Name(id='num', ctx=Load())], keywords=[]), simple=1), While(test=Compare(left=Name(id='n', ctx=Load()), ops=[Gt()], comparators=[Constant(value=0)]), body=[AnnAssign(target=Name(id='rem', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=BinOp(left=Name(id='n', ctx=Load()), op=BitAnd(), right=Constant(value=15)), simple=1), Assign(targets=[Subscript(value=Name(id='temp', ctx=Load()), slice=Name(id='temp_idx', ctx=Load()), ctx=Store())], value=Subscript(value=Name(id='hex_chars', ctx=Load()), slice=Name(id='rem', ctx=Load()), ctx=Load())), AugAssign(target=Name(id='temp_idx', ctx=Store()), op=Add(), value=Constant(value=1)), Assign(targets=[Name(id='n', ctx=Store())], value=BinOp(left=Name(id='n', ctx=Load()), op=RShift(), right=Constant(value=4)))], orelse=[]), While(test=Compare(left=Name(id='temp_idx', ctx=Load()), ops=[Gt()], comparators=[Constant(value=0)]), body=[AugAssign(target=Name(id='temp_idx', ctx=Store()), op=Sub(), value=Constant(value=1)), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Subscript(value=Name(id='temp', ctx=Load()), slice=Name(id='temp_idx', ctx=Load()), ctx=Load())), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1))], orelse=[]), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='\x00')), Return(value=Name(id='buf', ctx=Load()))], decorator_list=[], returns=Name(id='str', ctx=Load()), type_params=[]), FunctionDef(name='int_to_str', args=arguments(posonlyargs=[], args=[arg(arg='num', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[AnnAssign(target=Name(id='buf', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), value=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), args=[Call(func=Name(id='malloc', ctx=Load()), args=[Constant(value=128)], keywords=[]), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), simple=1), If(test=UnaryOp(op=Not(), operand=Name(id='buf', ctx=Load())), body=[Return(value=Constant(value=None))], orelse=[]), Assign(targets=[Name(id='is_negative', ctx=Store())], value=Constant(value=0)), Assign(targets=[Name(id='i', ctx=Store())], value=Constant(value=0)), If(test=Compare(left=Name(id='num', ctx=Load()), ops=[Eq()], comparators=[Constant(value=0)]), body=[Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='0')), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1)), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='\x00')), Return(value=Name(id='buf', ctx=Load()))], orelse=[]), If(test=Compare(left=Name(id='num', ctx=Load()), ops=[Lt()], comparators=[Constant(value=0)]), body=[Assign(targets=[Name(id='is_negative', ctx=Store())], value=Constant(value=1)), Assign(targets=[Name(id='num', ctx=Store())], value=UnaryOp(op=USub(), operand=Name(id='num', ctx=Load())))], orelse=[]), While(test=Compare(left=Name(id='num', ctx=Load()), ops=[Gt()], comparators=[Constant(value=0)]), body=[Assign(targets=[Name(id='rem', ctx=Store())], value=BinOp(left=Name(id='num', ctx=Load()), op=Mod(), right=Constant(value=10))), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=BinOp(left=Constant(value='0'), op=Add(), right=Name(id='rem', ctx=Load()))), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1)), Assign(targets=[Name(id='num', ctx=Store())], value=BinOp(left=Name(id='num', ctx=Load()), op=Div(), right=Constant(value=10)))], orelse=[]), If(test=Name(id='is_negative', ctx=Load()), body=[Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='-')), AugAssign(target=Name(id='i', ctx=Store()), op=Add(), value=Constant(value=1))], orelse=[]), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Store())], value=Constant(value='\x00')), Assign(targets=[Name(id='start', ctx=Store())], value=Constant(value=0)), Assign(targets=[Name(id='end', ctx=Store())], value=BinOp(left=Name(id='i', ctx=Load()), op=Sub(), right=Constant(value=1))), While(test=Compare(left=Name(id='start', ctx=Load()), ops=[Lt()], comparators=[Name(id='end', ctx=Load())]), body=[AnnAssign(target=Name(id='tr', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=Load()), value=Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='start', ctx=Load()), ctx=Load()), simple=1), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='start', ctx=Load()), ctx=Store())], value=Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='end', ctx=Load()), ctx=Load())), Assign(targets=[Subscript(value=Name(id='buf', ctx=Load()), slice=Name(id='end', ctx=Load()), ctx=Store())], value=Name(id='tr', ctx=Load())), AugAssign(target=Name(id='start', ctx=Store()), op=Add(), value=Constant(value=1)), AugAssign(target=Name(id='end', ctx=Store()), op=Sub(), value=Constant(value=1))], orelse=[]), Return(value=Name(id='buf', ctx=Load()))], decorator_list=[], returns=Name(id='str', ctx=Load()), type_params=[]), ClassDef(name='Item', bases=[], keywords=[], body=[AnnAssign(target=Name(id='data', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), simple=1), AnnAssign(target=Name(id='size', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()), simple=1)], decorator_list=[], type_params=[]), ClassDef(name='List', bases=[], keywords=[], body=[AnnAssign(target=Name(id='items', ctx=Store()), annotation=BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), simple=1), AnnAssign(target=Name(id='count', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='capacity', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()), value=Constant(value=4), simple=1), FunctionDef(name='__init__', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Store())], value=Constant(value=0)), Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='capacity', ctx=Store())], value=Constant(value=4)), Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Store())], value=Call(func=Name(id='malloc', ctx=Load()), args=[BinOp(left=Attribute(value=Name(id='self', ctx=Load()), attr='capacity', ctx=Load()), op=Mult(), right=Call(func=Attribute(value=Name(id='Item', ctx=Load()), attr='__sizeof__', ctx=Load()), args=[], keywords=[]))], keywords=[]))], decorator_list=[], type_params=[]), FunctionDef(name='__grow', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[If(test=Compare(left=Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Load()), ops=[GtE()], comparators=[Attribute(value=Name(id='self', ctx=Load()), attr='capacity', ctx=Load())]), body=[AugAssign(target=Attribute(value=Name(id='self', ctx=Load()), attr='capacity', ctx=Store()), op=Mult(), value=Constant(value=2)), Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Store())], value=Call(func=Name(id='realloc', ctx=Load()), args=[Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load()), BinOp(left=Attribute(value=Name(id='self', ctx=Load()), attr='capacity', ctx=Load()), op=Mult(), right=Call(func=Attribute(value=Name(id='Item', ctx=Load()), attr='__sizeof__', ctx=Load()), args=[], keywords=[]))], keywords=[]))], orelse=[])], decorator_list=[], type_params=[]), FunctionDef(name='append', args=arguments(posonlyargs=[], args=[arg(arg='self'), arg(arg='data', annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load()))), arg(arg='size', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='__grow', ctx=Load()), args=[], keywords=[])), AnnAssign(target=Name(id='item', ctx=Store()), annotation=BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), value=Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load()), slice=Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Load()), ctx=Load()), simple=1), Assign(targets=[Attribute(value=Name(id='item', ctx=Load()), attr='size', ctx=Store())], value=Name(id='size', ctx=Load())), Assign(targets=[Attribute(value=Name(id='item', ctx=Load()), attr='data', ctx=Store())], value=Call(func=Name(id='malloc', ctx=Load()), args=[BinOp(left=Name(id='size', ctx=Load()), op=Add(), right=Constant(value=1))], keywords=[])), Expr(value=Call(func=Name(id='memcpy', ctx=Load()), args=[Attribute(value=Name(id='item', ctx=Load()), attr='data', ctx=Load()), Name(id='data', ctx=Load()), Name(id='size', ctx=Load())], keywords=[])), Expr(value=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Set', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedChar', ctx=Load()), args=[BinOp(left=Attribute(value=Name(id='item', ctx=Load()), attr='data', ctx=Load()), op=Add(), right=Name(id='size', ctx=Load())), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[]), Constant(value='\x00')], keywords=[])), AugAssign(target=Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Store()), op=Add(), value=Constant(value=1))], decorator_list=[], type_params=[]), FunctionDef(name='get', args=arguments(posonlyargs=[], args=[arg(arg='self'), arg(arg='index', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[If(test=Compare(left=Name(id='index', ctx=Load()), ops=[GtE()], comparators=[Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Load())]), body=[Return(value=Constant(value=None))], orelse=[]), Return(value=Attribute(value=Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load()), slice=Name(id='index', ctx=Load()), ctx=Load()), attr='data', ctx=Load()))], decorator_list=[], returns=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt8T', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), type_params=[]), FunctionDef(name='__getitem__', args=arguments(posonlyargs=[], args=[arg(arg='self'), arg(arg='index', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Return(value=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='get', ctx=Load()), args=[Name(id='index', ctx=Load())], keywords=[]))], decorator_list=[], returns=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt8T', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())), type_params=[]), FunctionDef(name='free', args=arguments(posonlyargs=[], args=[arg(arg='self')], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[AnnAssign(target=Name(id='i', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()), value=Constant(value=0), simple=1), For(target=Name(id='i', ctx=Store()), iter=Call(func=Name(id='range', ctx=Load()), args=[Attribute(value=Name(id='self', ctx=Load()), attr='count', ctx=Load())], keywords=[]), body=[If(test=Compare(left=Attribute(value=Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Load()), attr='data', ctx=Load()), ops=[NotEq()], comparators=[Constant(value=0)]), body=[Expr(value=Call(func=Name(id='free', ctx=Load()), args=[Attribute(value=Subscript(value=Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Load()), attr='data', ctx=Load())], keywords=[]))], orelse=[])], orelse=[]), Expr(value=Call(func=Name(id='free', ctx=Load()), args=[Attribute(value=Name(id='self', ctx=Load()), attr='items', ctx=Load())], keywords=[]))], decorator_list=[], type_params=[])], decorator_list=[], type_params=[]), AnnAssign(target=Name(id='DEFINE_T', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CDefine', ctx=Load()), value=Constant(value=2423432423), simple=1), ClassDef(name='EnumTest', bases=[Attribute(value=Name(id='t', ctx=Load()), attr='CEnum', ctx=Load())], keywords=[], body=[AnnAssign(target=Name(id='A', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()), simple=1), AnnAssign(target=Name(id='B', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()), simple=1), AnnAssign(target=Name(id='C', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()), simple=1), AnnAssign(target=Name(id='Len', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()), simple=1)], decorator_list=[], type_params=[]), FunctionDef(name='main', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Attribute(value=Attribute(value=Name(id='w32', ctx=Load()), attr='win32console', ctx=Load()), attr='SetConsoleOutputCP', ctx=Load()), args=[Constant(value=65001)], keywords=[])), Expr(value=Call(func=Attribute(value=Attribute(value=Name(id='w32', ctx=Load()), attr='win32console', ctx=Load()), attr='SetConsoleCP', ctx=Load()), args=[Constant(value=65001)], keywords=[])), Assign(targets=[Name(id='d', ctx=Store())], value=Call(func=Name(id='OOPTest', ctx=Load()), args=[], keywords=[])), Assign(targets=[Name(id='l', ctx=Store())], value=Call(func=Name(id='List', ctx=Load()), args=[], keywords=[])), Assign(targets=[Name(id='nihao', ctx=Store())], value=Constant(value='你好!世界,这是一个可变列表')), Expr(value=Call(func=Attribute(value=Name(id='l', ctx=Load()), attr='append', ctx=Load()), args=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Addr', ctx=Load()), args=[Constant(value=114514)], keywords=[]), Call(func=Attribute(value=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), attr='__sizeof__', ctx=Load()), args=[], keywords=[])], keywords=[])), Expr(value=Call(func=Attribute(value=Name(id='l', ctx=Load()), attr='append', ctx=Load()), args=[Name(id='nihao', ctx=Load()), Call(func=Name(id='len', ctx=Load()), args=[Name(id='nihao', ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='列表取值0:'), Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='Cast', ctx=Load()), args=[Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), args=[Subscript(value=Name(id='l', ctx=Load()), slice=Constant(value=0), ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=Load())], keywords=[])], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='列表取值1:'), Call(func=Attribute(value=Name(id='l', ctx=Load()), attr='get', ctx=Load()), args=[Constant(value=1)], keywords=[])], keywords=[])), Expr(value=Call(func=Attribute(value=Name(id='l', ctx=Load()), attr='free', ctx=Load()), args=[], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='结束')], keywords=[])), AnnAssign(target=Name(id='E', ctx=Store()), annotation=Name(id='EnumTest', ctx=Load()), value=Attribute(value=Name(id='EnumTest', ctx=Load()), attr='B', ctx=Load()), simple=1), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Name(id='E', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='EnumTest', ctx=Load()), attr='Len', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='EnumTest', ctx=Load()), args=[Constant(value=1)], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='type', ctx=Load()), args=[Attribute(value=Name(id='EnumTest', ctx=Load()), attr='B', ctx=Load())], keywords=[])], keywords=[])), Assign(targets=[Name(id='u', ctx=Store())], value=Call(func=Name(id='Union', ctx=Load()), args=[], keywords=[])), Assign(targets=[Attribute(value=Attribute(value=Name(id='u', ctx=Load()), attr='A', ctx=Load()), attr='a', ctx=Store())], value=Constant(value=114514)), Assign(targets=[Attribute(value=Attribute(value=Name(id='u', ctx=Load()), attr='A', ctx=Load()), attr='b', ctx=Store())], value=Constant(value=222222)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='u.A.a'), Attribute(value=Attribute(value=Name(id='u', ctx=Load()), attr='A', ctx=Load()), attr='a', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='u.A.b'), Attribute(value=Attribute(value=Name(id='u', ctx=Load()), attr='A', ctx=Load()), attr='b', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='u.A.c'), Attribute(value=Attribute(value=Name(id='u', ctx=Load()), attr='B', ctx=Load()), attr='c', ctx=Load())], keywords=[])), Assign(targets=[Name(id='wb', ctx=Store())], value=Call(func=Name(id='WBIT', ctx=Load()), args=[], keywords=[])), Assign(targets=[Attribute(value=Name(id='wb', ctx=Load()), attr='a', ctx=Store())], value=Constant(value=1)), Assign(targets=[Attribute(value=Name(id='wb', ctx=Load()), attr='b', ctx=Store())], value=Constant(value=1)), Assign(targets=[Attribute(value=Name(id='wb', ctx=Load()), attr='c', ctx=Store())], value=Constant(value=1)), Assign(targets=[Attribute(value=Name(id='wb', ctx=Load()), attr='d', ctx=Store())], value=Constant(value=12)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='wb', ctx=Load()), attr='a', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='wb', ctx=Load()), attr='b', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='wb', ctx=Load()), attr='c', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='wb', ctx=Load()), attr='d', ctx=Load())], keywords=[])), Assign(targets=[Attribute(value=Name(id='wb', ctx=Load()), attr='a', ctx=Store())], value=Constant(value=2)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='wb', ctx=Load()), attr='a', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Attribute(value=Name(id='wb', ctx=Load()), attr='__sizeof__', ctx=Load()), args=[], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='type', ctx=Load()), args=[Name(id='wb', ctx=Load())], keywords=[])], keywords=[])), Assign(targets=[Name(id='ble', ctx=Store())], value=Call(func=Name(id='BLE', ctx=Load()), args=[], keywords=[])), Assign(targets=[Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Store())], value=Constant(value=1131796)), Assign(targets=[Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Store())], value=Constant(value=1131796)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Load())], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='a:'), Call(func=Name(id='int_to_str', ctx=Load()), args=[Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='a_hex:'), Call(func=Name(id='str_to_hex', ctx=Load()), args=[Call(func=Name(id='int_to_str', ctx=Load()), args=[Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load())], keywords=[])], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load()), slice=Constant(value=1), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load()), slice=Constant(value=2), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='a', ctx=Load()), slice=Constant(value=3), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Load()), slice=Constant(value=0), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Load()), slice=Constant(value=1), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Load()), slice=Constant(value=2), ctx=Load())], keywords=[])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Name(id='int_to_hex', ctx=Load()), args=[Subscript(value=Attribute(value=Name(id='ble', ctx=Load()), attr='b', ctx=Load()), slice=Constant(value=3), ctx=Load())], keywords=[])], keywords=[])), Assign(targets=[Name(id='li', ctx=Store())], value=Constant(value=4294967297)), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Name(id='DEFINE_T', ctx=Load())], keywords=[])), If(test=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='CIf', ctx=Load()), args=[Compare(left=Name(id='DEFINE_T', ctx=Load()), ops=[Eq()], comparators=[Constant(value=2423432423)])], keywords=[]), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='DEFINE_T == 2423432423')], keywords=[]))], orelse=[If(test=Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='CIf', ctx=Load()), args=[Compare(left=Name(id='DEFINE_T', ctx=Load()), ops=[Eq()], comparators=[Constant(value=123)])], keywords=[]), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='DEFINE_T == 123')], keywords=[]))], orelse=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='DEFINE_T != 2423432423 and DEFINE_T != 123')], keywords=[]))])])], decorator_list=[], returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), type_params=[]), ClassDef(name='LIWORK', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', ctx=Load()), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', ctx=Load()), simple=1)], decorator_list=[], type_params=[]), ClassDef(name='Union', bases=[Attribute(value=Name(id='t', ctx=Load()), attr='CUnion', ctx=Load())], keywords=[], body=[ClassDef(name='A', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ctx=Load()), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ctx=Load()), simple=1)], decorator_list=[], type_params=[]), ClassDef(name='B', bases=[], keywords=[], body=[AnnAssign(target=Name(id='c', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt16T', ctx=Load()), simple=1), AnnAssign(target=Name(id='d', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ctx=Load()), simple=1)], decorator_list=[], type_params=[])], decorator_list=[], type_params=[]), ClassDef(name='WBIT', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='Bit', ctx=Load()), args=[Constant(value=1)], keywords=[])), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='Bit', ctx=Load()), args=[Constant(value=1)], keywords=[])), simple=1), AnnAssign(target=Name(id='c', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='Bit', ctx=Load()), args=[Constant(value=1)], keywords=[])), simple=1), AnnAssign(target=Name(id='d', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Call(func=Attribute(value=Name(id='t', ctx=Load()), attr='Bit', ctx=Load()), args=[Constant(value=5)], keywords=[])), simple=1)], decorator_list=[], type_params=[]), ClassDef(name='BLE', bases=[], keywords=[], body=[AnnAssign(target=Name(id='a', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='BigEndian', ctx=Load())), simple=1), AnnAssign(target=Name(id='b', ctx=Store()), annotation=BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), op=BitOr(), right=Attribute(value=Name(id='t', ctx=Load()), attr='LittleEndian', ctx=Load())), simple=1)], decorator_list=[], type_params=[])], type_ignores=[]) - -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='OOPTest2', ctx=Load()), op=BitOr(), righ... -[GetCTypeInfo] Node type: Name, dump: Name(id='OOPTest2', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Name(id='Item', ctx=Load()), op=BitOr(), right=At... -[GetCTypeInfo] Node type: Name, dump: Name(id='Item', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CDefine', ct... -[GetCTypeInfo-Attribute] 查询: 'CDefine' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='BigEndian', ... -[GetCTypeInfo-Attribute] 查询: 'BigEndian' ModulePath: t -[GetCTypeInfo] Node type: BinOp, dump: BinOp(left=Attribute(value=Name(id='t', ctx=Load()), attr='C... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='LittleEndian... -[GetCTypeInfo-Attribute] 查询: 'LittleEndian' ModulePath: t -[GetCTypeInfo] Node type: Subscript, dump: Subscript(value=Name(id='list', ctx=Load()), slice=Tuple(elt... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='Struct1', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CDefine', ct... -[GetCTypeInfo-Attribute] 查询: 'CDefine' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExtern', ct... -[GetCTypeInfo-Attribute] 查询: 'CExtern' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExtern', ct... -[GetCTypeInfo-Attribute] 查询: 'CExtern' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Constant, dump: Constant(value=None)... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedInt... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedInt' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedCha... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedChar' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BYTE', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt16T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt64T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='str', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CShort', ctx... -[GetCTypeInfo-Attribute] 查询: 'CShort' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CShort', ctx... -[GetCTypeInfo-Attribute] 查询: 'CShort' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedSho... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedShort' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedSho... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedShort' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedLon... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CLong', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CLong' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedLon... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedLong' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='WORD', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='WORD', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='DWORD', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='DWORD', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedInt... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat', ctx... -[GetCTypeInfo-Attribute] 查询: 'CFloat' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CDouble', ct... -[GetCTypeInfo-Attribute] 查询: 'CDouble' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat8T', c... -[GetCTypeInfo-Attribute] 查询: 'CFloat8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat16T', ... -[GetCTypeInfo-Attribute] 查询: 'CFloat16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat32T', ... -[GetCTypeInfo-Attribute] 查询: 'CFloat32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat64T', ... -[GetCTypeInfo-Attribute] 查询: 'CFloat64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CFloat128T',... -[GetCTypeInfo-Attribute] 查询: 'CFloat128T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt8T', ctx... -[GetCTypeInfo-Attribute] 查询: 'CInt8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt16T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt8T', ct... -[GetCTypeInfo-Attribute] 查询: 'CUInt8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt16T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt64T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt8T', ctx... -[GetCTypeInfo-Attribute] 查询: 'CInt8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt16T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt32T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ct... -[GetCTypeInfo-Attribute] 查询: 'CInt64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt8T', ct... -[GetCTypeInfo-Attribute] 查询: 'CUInt8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt16T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt32T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUInt64T', c... -[GetCTypeInfo-Attribute] 查询: 'CUInt64T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar8T', ct... -[GetCTypeInfo-Attribute] 查询: 'CChar8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar16T', c... -[GetCTypeInfo-Attribute] 查询: 'CChar16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar32T', c... -[GetCTypeInfo-Attribute] 查询: 'CChar32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar8T', ct... -[GetCTypeInfo-Attribute] 查询: 'CChar8T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar16T', c... -[GetCTypeInfo-Attribute] 查询: 'CChar16T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar32T', c... -[GetCTypeInfo-Attribute] 查询: 'CChar32T' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx... -[GetCTypeInfo-Attribute] 查询: 'CSizeT' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CVoid' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='CONSOLE_SCREEN_BUFFER_INFO', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='CONSOLE_CURSOR_INFO', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='CONSOLE_CURSOR_INFO', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CConst', ctx... -[GetCTypeInfo-Attribute] 查询: 'CConst' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='VOIDPTR', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CConst', ctx... -[GetCTypeInfo-Attribute] 查询: 'CConst' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='VOIDPTR', ctx=Load())... -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='INPUT_RECORD', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='INPUT_RECORD', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='ULONG', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='SMALL_RECT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='BOOL', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='SMALL_RECT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='SMALL_RECT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='CHAR_INFO', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CUnsignedCha... -[GetCTypeInfo-Attribute] 查询: 'CUnsignedChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=... -[GetCTypeInfo-Attribute] 查询: 'State' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExtern', ct... -[GetCTypeInfo-Attribute] 查询: 'CExtern' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CExport', ct... -[GetCTypeInfo-Attribute] 查询: 'CExport' ModulePath: t -[GetCTypeInfo] Node type: Name, dump: Name(id='UINT', ctx=Load())... -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CChar', ctx=... -[GetCTypeInfo-Attribute] 查询: 'CChar' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CPtr', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CPtr' ModulePath: t diff --git a/Test/regression_test.py b/Test/regression_test.py new file mode 100644 index 0000000..2f8007e --- /dev/null +++ b/Test/regression_test.py @@ -0,0 +1,334 @@ +#!/usr/bin/env python3 +"""TransPyC 回归测试脚本 + +自动遍历 Test/ 目录下所有含 project.json 的项目目录, +通过 os.system("python ../Projectrans.py --project ...") 执行编译。 +所有项目编译完成后,多线程执行编译结果,超时 5 秒强制结束。 +stdout 出现 failed/error 等字样也汇总到错误列表,并展示匹配行及上下 5 行。 +""" +import os +import sys +import json +import time +import subprocess +import re + +# 测试目录 +TEST_DIR = os.path.dirname(os.path.abspath(__file__)) +# 项目根目录(Projectrans.py 所在位置) +PROJECT_ROOT = os.path.dirname(TEST_DIR) +# Projectrans.py 路径 +PROJECTRANS = os.path.join(PROJECT_ROOT, "Projectrans.py") + +# 运行超时(秒) +RUN_TIMEOUT = 30 +# 编译超时(秒) +COMPILE_TIMEOUT = 300 + +# stdout 中匹配这些关键词则视为运行失败 +_FAIL_PATTERNS = re.compile( + r'(?i)\b(failed|error|traceback|exception|aborted|segmentation fault|core dumped)\b' +) +# 排除 "0 failed" 这类成功摘要行,以及测试输出中的 "error" 误报 +_PASS_PATTERNS = re.compile( + r'\b0\s+failed\b' + r'|\bError\s+(handling|code|message|check|report|status|info|detail|test)\b' + r'|\+--\s*Error\s' # section headers like "+-- Error handling --+" + r'|\bclear\s+error\b' # "[PASS] clear error clears code" + r'|\berror\s+(code|message)\b' # "error code is set", "error message set" + r'|\[PASS\].*\berror\b' # "[PASS] ... error ..." test assertions + r'|\[FAIL\].*\berror\b', # "[FAIL] ... error ..." test assertions + re.IGNORECASE +) + + +def find_test_projects(): + """查找所有含 project.json 的测试项目目录""" + projects = [] + for name in sorted(os.listdir(TEST_DIR)): + proj_dir = os.path.join(TEST_DIR, name) + if not os.path.isdir(proj_dir): + continue + proj_json = os.path.join(proj_dir, "project.json") + if os.path.isfile(proj_json): + projects.append((name, proj_dir, proj_json)) + return projects + + +def compile_project(name, proj_dir, proj_json_path): + """编译单个测试项目,返回 (success, elapsed, output)""" + cmd = f'python -u "{PROJECTRANS}" --project "{proj_json_path}" --clean' + + start = time.time() + result = subprocess.run( + cmd, + shell=True, + capture_output=True, + text=True, + encoding='utf-8', + errors='replace', + cwd=proj_dir, + timeout=COMPILE_TIMEOUT, + ) + elapsed = time.time() - start + + stdout = result.stdout or "" + stderr = result.stderr or "" + combined = stdout + stderr + + success = result.returncode == 0 + return (success, elapsed, combined) + + +def find_executables(output_dir): + """在 output 目录中查找可执行文件""" + exes = [] + if not os.path.isdir(output_dir): + return exes + for f in os.listdir(output_dir): + fpath = os.path.join(output_dir, f) + if os.path.isfile(fpath) and (f.endswith('.exe') or f.endswith('.bin')): + exes.append(fpath) + return exes + + +def run_executable(exe_path): + """运行单个可执行文件,返回 (returncode, stdout, stderr, timed_out) + + 超时 RUN_TIMEOUT 秒强制结束。 + 使用 CREATE_NEW_CONSOLE 创建独立控制台窗口运行程序, + 避免某些程序调用 SetConsoleOutputCP(65001) 后在非控制台模式下崩溃。 + 由于新控制台窗口中 stdout 是真正的控制台句柄,无法通过管道捕获输出。 + """ + try: + CREATE_NEW_CONSOLE = 0x00000010 + proc = subprocess.Popen( + [exe_path], + cwd=os.path.dirname(exe_path), + creationflags=CREATE_NEW_CONSOLE, + ) + try: + proc.wait(timeout=RUN_TIMEOUT) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait() + return (-1, "", "超时(强制终止)", True) + + return (proc.returncode, "", "", False) + except Exception as e: + return (-1, "", str(e), False) + + +def extract_error_context(stdout, stderr, context_lines=5): + """检查 stdout/stderr 中是否包含 failed/error 等关键词。 + + 返回 (matched_line, context_str) 或 None。 + context_str 包含匹配行及上下 context_lines 行。 + """ + combined = (stdout + "\n" + stderr).strip() + if not combined: + return None + + lines = combined.split('\n') + for i, line in enumerate(lines): + if _FAIL_PATTERNS.search(line): + # 跳过 "0 failed" 这类成功摘要行 + if _PASS_PATTERNS.search(line): + continue + # 提取上下 context_lines 行 + start = max(0, i - context_lines) + end = min(len(lines), i + context_lines + 1) + context_parts = [] + for j in range(start, end): + marker = " >>>" if j == i else " " + context_parts.append(f"{marker} {lines[j]}") + return (line.strip(), '\n'.join(context_parts)) + return None + + +def main(): + print("=" * 70) + print("TransPyC 回归测试") + print("=" * 70) + print() + + projects = find_test_projects() + total = len(projects) + print(f"发现 {total} 个测试项目\n") + + # ========== 阶段一:编译所有项目 ========== + print("=" * 70) + print("阶段一:编译所有项目") + print("=" * 70) + + compiled = [] # (name, proj_dir, proj_json, compile_ok, elapsed, output) + compile_passed = 0 + compile_failed = 0 + + for idx, (name, proj_dir, proj_json) in enumerate(projects, 1): + print(f"[{idx}/{total}] 编译 {name} ...", end=" ", flush=True) + try: + compile_ok, elapsed, output = compile_project(name, proj_dir, proj_json) + except subprocess.TimeoutExpired: + print("编译超时") + compiled.append((name, proj_dir, proj_json, False, COMPILE_TIMEOUT, "编译超时(5分钟)")) + compile_failed += 1 + continue + except Exception as e: + print(f"异常: {e}") + compiled.append((name, proj_dir, proj_json, False, 0.0, str(e))) + compile_failed += 1 + continue + + status = "通过" if compile_ok else "失败" + print(f"{status} ({elapsed:.1f}s)") + compiled.append((name, proj_dir, proj_json, compile_ok, elapsed, output)) + if compile_ok: + compile_passed += 1 + else: + compile_failed += 1 + + print(f"\n编译阶段: 通过 {compile_passed}, 失败 {compile_failed}\n") + + # ========== 阶段二:运行所有编译成功的可执行文件 ========== + print("=" * 70) + print("阶段二:运行所有可执行文件") + print("=" * 70) + + # 收集所有需要运行的可执行文件 + run_tasks = [] # (project_name, exe_path) + for name, proj_dir, proj_json, compile_ok, elapsed, output in compiled: + if not compile_ok: + continue + try: + with open(proj_json, 'r', encoding='utf-8') as f: + proj_config = json.load(f) + except Exception: + continue + output_dir = os.path.join(proj_dir, proj_config.get('output_dir', './output')) + output_dir = os.path.abspath(output_dir) + for exe in find_executables(output_dir): + run_tasks.append((name, exe)) + + print(f"找到 {len(run_tasks)} 个可执行文件\n") + + run_results = {} # project_name -> list of (exe_name, returncode, stdout, stderr, timed_out) + run_passed = 0 + run_failed = 0 + + if run_tasks: + # 串行运行,避免并发导致的资源竞争(控制台输出、堆分配器等) + for proj_name, exe_path in run_tasks: + exe_name = os.path.basename(exe_path) + try: + returncode, stdout, stderr, timed_out = run_executable(exe_path) + except Exception as e: + returncode, stdout, stderr, timed_out = -1, "", str(e), False + + if proj_name not in run_results: + run_results[proj_name] = [] + run_results[proj_name].append((exe_name, returncode, stdout, stderr, timed_out)) + + # 汇总运行结果 + for name, proj_dir, proj_json, compile_ok, elapsed, output in compiled: + if not compile_ok: + continue + exe_results = run_results.get(name, []) + if not exe_results: + continue + + project_run_ok = True + for exe_name, returncode, stdout, stderr, timed_out in exe_results: + if timed_out or returncode != 0: + project_run_ok = False + break + if extract_error_context(stdout, stderr): + project_run_ok = False + break + + status = "通过" if project_run_ok else "失败" + print(f" {name}: {status}") + if project_run_ok: + run_passed += 1 + else: + run_failed += 1 + + print(f"\n运行阶段: 通过 {run_passed}, 失败 {run_failed}\n") + + # ========== 汇总报告 ========== + print("=" * 70) + print("回归测试报告") + print("=" * 70) + total_failed = compile_failed + run_failed + total_passed = compile_passed - run_failed # 编译通过但运行失败的不算通过 + print(f"总计: {total} 通过: {total_passed} 失败: {total_failed}") + print() + + if total_failed > 0: + print("-" * 70) + print("失败项目详情:") + print("-" * 70) + + # 编译失败 + for name, proj_dir, proj_json, compile_ok, elapsed, output in compiled: + if compile_ok: + continue + print(f"\n【{name}】编译失败") + lines = output.strip().split("\n") if output else [] + if len(lines) > 300: + print(f" ... (省略前 {len(lines) - 300} 行) ...") + lines = lines[-300:] + for line in lines: + print(f" {line}") + + # 运行失败 + for name, proj_dir, proj_json, compile_ok, elapsed, output in compiled: + if not compile_ok: + continue + exe_results = run_results.get(name, []) + if not exe_results: + continue + + has_failure = False + for exe_name, returncode, stdout, stderr, timed_out in exe_results: + if timed_out or returncode != 0 or extract_error_context(stdout, stderr): + has_failure = True + break + + if not has_failure: + continue + + print(f"\n【{name}】运行失败 (编译耗时 {elapsed:.1f}s)") + for exe_name, returncode, stdout, stderr, timed_out in exe_results: + if timed_out: + print(f" [运行] {exe_name}: 超时(5秒强制终止)") + continue + if returncode != 0: + print(f" [运行] {exe_name}: 退出码 {returncode}") + if stderr.strip(): + print(f" stderr: {stderr.strip()[:300]}") + continue + + # 检查错误关键词,展示匹配行及上下 5 行 + error_ctx = extract_error_context(stdout, stderr) + if error_ctx: + matched_line, context_str = error_ctx + print(f" [运行] {exe_name}: 输出含错误关键词") + print(f" 匹配行: {matched_line}") + print(f" 上下文:") + for ctx_line in context_str.split('\n'): + print(f" {ctx_line}") + print() + + print("=" * 70) + if total_failed == 0: + print("所有测试通过!") + else: + print(f"有 {total_failed} 个测试失败,请检查上方详情。") + print("=" * 70) + + return 1 if total_failed > 0 else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/TransPyC.py b/TransPyC.py index 4e17cc3..6d17236 100644 --- a/TransPyC.py +++ b/TransPyC.py @@ -1,715 +1,15 @@ -# TransPyC 入口程序 - -import sys -import os -import ast -import json -import struct -# 添加lib目录到Python路径 -sys.path.append(os.path.join(os.path.dirname(__file__), 'lib', 'includes')) -from lib.includes import c -from lib.includes import t -from lib.constants.config import ( - DEFAULT_INPUT_FILE, DEFAULT_OUTPUT_FILE, - DEFAULT_COMPILE_COMMAND, - DEFAULT_COMPILE_FLAGS, ERROR_MESSAGES, - HELP_MESSAGE, DEFAULT_METADATA -) -from lib.utils.helpers import ( - DetectFileType, ExecuteCommand, - AppendFileContent -) -from lib.core.translator import Translator - - -def SerializeSymbolTable(SymbolTable: dict) -> bytes: - """将符号表序列化为二进制格式 - - 格式: - - 4字节: JSON数据长度(小端序) - - N字节: JSON数据(UTF-8编码) - - Args: - SymbolTable: 符号表字典 - - Returns: - 二进制字节数据 - """ - JsonData = json.dumps(SymbolTable, ensure_ascii=False).encode('utf-8') - length = len(JsonData) - # 使用4字节小端序整数表示长度 - header = struct.pack(' dict: - """从二进制数据反序列化符号表 - - Args: - data: 二进制字节数据 - - Returns: - 符号表字典 - """ - if len(data) < 4: - raise ValueError("Invalid symbin file: data too short") - # 解析4字节长度头(小端序) - length = struct.unpack(' -o [-debug ] - if I + 1 < len(sys.argv): - InputFile = sys.argv[I + 1] - I += 2 - - # 解析可选参数 - OutputFile = None - DebugFile = None - while I < len(sys.argv) and sys.argv[I].startswith('-'): - if sys.argv[I] == '-o': - if I + 1 < len(sys.argv): - OutputFile = sys.argv[I + 1] - I += 2 - else: - print(f'Error: -o requires an argument') - sys.exit(1) - elif sys.argv[I] == '-debug': - if I + 1 < len(sys.argv): - DebugFile = sys.argv[I + 1] - I += 2 - else: - print(f'Error: -debug requires an argument') - sys.exit(1) - else: - break - - # 如果没有指定输出文件,使用默认名称 - if not OutputFile: - OutputFile = InputFile.replace('.py', '.symbin').replace('.c', '.symbin') - - # 执行预处理 - self.Args['PreSym'] = { - 'input': InputFile, - 'output': OutputFile, - 'debug': DebugFile - } - else: - print(f'Error: -presym requires an argument') - sys.exit(1) - elif sys.argv[I] == '-e' or sys.argv[I] == '--encoding': - if I + 1 < len(sys.argv): - self.Args['Encoding'] = sys.argv[I + 1] - I += 2 - else: - print(f'Error: -e/--encoding requires an argument') - sys.exit(1) - elif sys.argv[I] == '--triple': - if I + 1 < len(sys.argv): - self.triple = sys.argv[I + 1] - I += 2 - else: - print(f'Error: --triple requires an argument') - sys.exit(1) - elif sys.argv[I] == '--datalayout': - if I + 1 < len(sys.argv): - self.datalayout = sys.argv[I + 1] - I += 2 - else: - print(f'Error: --datalayout requires an argument') - sys.exit(1) - else: - print(f'Error: Unknown argument {sys.argv[I]}') - sys.exit(1) - - # 检查是否有预处理符号文件的请求,如果有则跳过输入输出检查 - if 'PreSym' not in self.Args and ('Input' not in self.Args or 'Output' not in self.Args): - print(ERROR_MESSAGES['MISSING_ARGS']) - print(HELP_MESSAGE) - sys.exit(1) - - def CompileAndRun(self, OutputFile): - """编译并运行生成的C代码""" - # 获取编译命令 - CompileCmd = self.Args.get('CompileCommand', DEFAULT_COMPILE_COMMAND) - CompileFlags = self.Args.get('CompileFlags', DEFAULT_COMPILE_FLAGS) - - # 构建编译命令 - FullCompileCmd = f'{CompileCmd} {CompileFlags} {OutputFile} -o {OutputFile}.exe' - print(f'Compiling: {FullCompileCmd}') - - # 执行编译命令 - try: - CompileResult = ExecuteCommand(FullCompileCmd) - if CompileResult: - print('Compilation successful!') - - # 检查是否需要运行 - if self.Args.get('Run', False): - RunArgs = self.Args.get('RunArgs', '') - RunCmd = f'{OutputFile}.exe {RunArgs}'.strip() - print(f'Running: {RunCmd}') - - # 执行运行命令 - RunResult = ExecuteCommand(RunCmd) - if RunResult: - print('Execution output:') - print(RunResult.stdout) - if RunResult.stderr: - print('Execution errors:') - print(RunResult.stderr) - except Exception as e: - print(f'{ERROR_MESSAGES["COMPILE_FAILED"]}: {e}') - - def WriteDebugInfo(self, content): - """写入调试信息到指定文件""" - # 获取调试文件路径 - if 'Debug' in self.Args: - DebugFile = self.Args['Debug'] - else: - DebugFile = self.Args.get('Output', '').replace('.c', '.p2c') - - if DebugFile: - AppendFileContent(DebugFile, content) - - def PythonToC(self, InputFile, OutputFile): - """Python到C的转换""" - # 获取编码参数 - encoding = self.Args.get('Encoding', 'utf-8') - - # 设置调试文件路径(使用 .p2c 扩展名) - if 'Debug' in self.Args: - DebugFile = self.Args['Debug'] - else: - # 默认使用 .p2c 文件 - DebugFile = OutputFile.replace('.c', '.p2c') - - # 设置翻译器的调试文件 - self.translator.SetDebugFile(DebugFile) - - # 先清空调试文件 - with open(DebugFile, 'w', encoding=encoding) as f: - f.write('') - - # 解析辅助文件,提取符号信息 - if self.HelperFiles: - self.translator.ParseHelperFiles(self.HelperFiles, encoding) - - # 加载注解文件,提取类型定义 - if self.AnnotationFiles: - self.translator.LoadAnnotationFiles(self.AnnotationFiles) - - # 获取编码参数 - encoding = self.Args.get('Encoding', 'utf-8') - with open(InputFile, 'r', encoding=encoding) as F: - Content = F.read() - - # 保存原始代码行 - self.translator.OriginalLines = Content.split('\n') - self.translator.Content = Content - - # 解析Python代码为AST - Tree = ast.parse(Content) - - # 解析文件以提取类型信息(用于 EmbeddedAssignments) - self.translator.ParsePythonFile(InputFile, encoding) - - # 写入AST树信息(压缩格式) - with open(DebugFile, 'a', encoding=encoding) as f: - f.write('=== AST Tree (Compact) ===\n') - f.write(ast.dump(Tree)) - f.write('\n\n') - - Target = 'llvm' - CCode = self.translator.GenerateCCode(Tree, target=Target) - - import datetime - timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - filename = os.path.basename(OutputFile) - - encoding = self.Args.get('Encoding', 'utf-8') - with open(OutputFile, 'w', encoding=encoding) as F: - F.write(CCode) - F.write('\n') - - def CToPython(self, InputFile, OutputFile, HeaderFiles): - """C到Python的转换(暂时禁用)""" - print("C到Python的转换功能暂时禁用,请使用Python到C的转换功能。") - - def AddSymbol(self, SymbolFiles): - """添加符号文件 - - Args: - SymbolFiles: 符号文件或符号文件列表 - """ - if isinstance(SymbolFiles, list): - self.SymbolFiles.extend(SymbolFiles) - else: - self.SymbolFiles.append(SymbolFiles) - - # 收集文件路径和编码 - HelperFiles = [] - encodings = [] - for SymbolFile in self.SymbolFiles: - FilePath = SymbolFile.FilePath - encoding = SymbolFile.encoding - if FilePath: - HelperFiles.append(FilePath) - encodings.append(encoding) - - # 解析辅助文件 - if HelperFiles: - # 暂时使用第一个文件的编码 - encoding = encodings[0] if encodings else 'utf-8' - self.translator.ParseHelperFiles(HelperFiles, encoding) - - def Convert(self, OutputFilename=None, SourceFilename=None, target='llvm'): - """转换代码 - - Args: - OutputFilename: 输出文件名(用于模板渲染) - SourceFilename: 源文件路径(用于设置CurrentFile,影响导入模块的查找) - target: 目标代码类型,仅支持 'llvm' - - Returns: - 如果debug是字符串,则返回生成的代码 - 如果debug是True,则返回生成的代码和调试信息 - """ - if not self.code: - print('Error: No code provided') - return None - - from lib.core.Handles.HandlesImports import ImportHandle - ImportHandle._struct_load_cache.clear() - - # 如果提供了 SourceFilename,先设置 CurrentFile - # 这样导入模块时会相对于源文件所在目录查找 - if SourceFilename: - self.translator.CurrentFile = SourceFilename - - # 加载注解文件,提取类型定义 - if self.AnnotationFiles: - self.translator.LoadAnnotationFiles(self.AnnotationFiles) - - # 保存原始代码行 - self.translator.OriginalLines = self.code.split('\n') - - # 解析Python代码为AST - Tree = ast.parse(self.code) - - # 从源代码直接预扫描 import 语句,注册别名 - # 注意:不能依赖 Tree 中的 import 节点,因为 ParsePythonFile 可能修改了 AST - if not getattr(self.translator, '_import_aliases', None): - self.translator._import_aliases = {} - if not getattr(self.translator, '_imported_modules', None): - self.translator._imported_modules = set() - _prescan_tree = ast.parse(self.code) - for _node in ast.iter_child_nodes(_prescan_tree): - if isinstance(_node, ast.Import): - for _alias in _node.names: - _name = _alias.name - if _name in ('c', 't'): - continue - self.translator._imported_modules.add(_name) - if _alias.asname: - self.translator._import_aliases[_alias.asname] = _name - elif isinstance(_node, ast.ImportFrom): - _module_name = _node.module - if _module_name and _module_name not in ('c', 't'): - self.translator._imported_modules.add(_module_name) - for _alias in _node.names: - if _alias.asname: - self.translator._import_aliases[_alias.asname] = f"{_module_name}.{_alias.name}" - - # 解析代码以提取类型信息(用于 EmbeddedAssignments 和 TypedefAssignments) - # 创建临时文件路径用于解析 - import tempfile - import os - with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as f: - f.write(self.code) - TempFile = f.name - try: - # UpdateCurrentFile=False 表示不修改 CurrentFile - if SourceFilename: - self.translator.ParsePythonFile(TempFile, UpdateCurrentFile=False) - else: - self.translator.ParsePythonFile(TempFile) - finally: - os.unlink(TempFile) - - import datetime - timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - - if self.triple: - self.translator.triple = self.triple - if self.datalayout: - self.translator.datalayout = self.datalayout - - # 生成代码 - code = self.translator.GenerateCCode(Tree, target='llvm') - filename = os.path.basename(OutputFilename) if OutputFilename else 'generated.ll' - - # 处理调试信息 - if isinstance(self.config.debug, str): - # 如果debug是字符串,写入调试信息到文件 - with open(self.config.debug, 'w', encoding='utf-8') as f: - f.write('=== Symbol Table ===\n') - f.write(str(self.translator.SymbolTable) + '\n\n') - f.write('=== AST Tree ===\n') - f.write(ast.dump(Tree, indent=2) + '\n\n') - f.write('=== Export Table ===\n') - f.write(self.translator.ExportTable.to_json() + '\n\n') - f.write('=== Generated Code ===\n') - f.write(code + '\n') - return code - elif self.config.debug: - # 如果debug是True,返回生成的代码和调试信息 - DebugInfo = { - 'SymbolTable': self.translator.SymbolTable, - 'ast_tree': ast.dump(Tree, indent=2), - 'export_table': self.translator.ExportTable.to_dict(), - 'generated_code': code - } - return code, DebugInfo - else: - # 如果debug是False,只返回生成的代码 - return code - - def Run(self): - """主运行函数""" - # 检查是否有命令行参数 - if len(sys.argv) > 1: - # 有命令行参数,使用 ParseArgs 方法解析 - self.ParseArgs() - - # 检查是否有预处理符号文件的请求 - if 'PreSym' in self.Args: - PresymConfig = self.Args['PreSym'] - InputFile = PresymConfig['input'] - OutputFile = PresymConfig['output'] - DebugFile = PresymConfig['debug'] - - # 获取编码参数 - encoding = self.Args.get('Encoding', 'utf-8') - - # 推断文件类型 - FileType = 'py' if InputFile.endswith('.py') else 'c' if InputFile.endswith('.c') else None - - # 创建 SymbolFile 对象,传入编码参数 - SymbolFile = SymbolFile(file=InputFile, type=FileType, encoding=encoding) - - # 调用 PreProcessSymbol - if DebugFile: - BinaryData, DebugInfo = TransPyC.PreProcessSymbol(SymbolFile, debug=True) - # 写入调试文件 - with open(DebugFile, 'w', encoding=encoding) as f: - f.write(DebugInfo) - print(f"Debug info written to: {DebugFile}") - else: - BinaryData = TransPyC.PreProcessSymbol(SymbolFile, debug=False) - - # 写入二进制符号文件 - with open(OutputFile, 'wb') as f: - f.write(BinaryData) - - print(f"Symbol file generated: {OutputFile}") - return - - InputFile = self.Args['Input'] - OutputFile = self.Args['Output'] - else: - # 没有命令行参数,使用默认的测试文件名称 - InputFile = DEFAULT_INPUT_FILE - OutputFile = DEFAULT_OUTPUT_FILE - print('Using default test files: test.py -> test.c') - - FileType = DetectFileType(InputFile) - - if FileType == '.py': - self.PythonToC(InputFile, OutputFile) - # 检查是否需要编译和运行 - if 'CompileCommand' in self.Args or self.Args.get('Run', False): - self.CompileAndRun(OutputFile) - elif FileType == '.c': - self.CToPython(InputFile, OutputFile, self.HeaderFiles) - else: - print(f'Error: Unsupported file type {FileType}') - sys.exit(1) - - -if __name__ == '__main__': - trans = TransPyC() - if 'SliceLevel' in trans.Args: - trans.SliceLevel = trans.Args['SliceLevel'] - trans.Run() +# TransPyC 入口程序 +# 拆分后的模块位于 lib/Shell/ 目录下 +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), 'lib', 'includes')) + +from lib.Shell import ( + SerializeSymbolTable, deSerializeSymbolTable, + SymbolFile, Config, TransPyC +) + +__all__ = ['SerializeSymbolTable', 'deSerializeSymbolTable', 'SymbolFile', 'Config', 'TransPyC'] + +if __name__ == '__main__': + TransPyC().Run() diff --git a/blackhole.py b/blackhole.py deleted file mode 100644 index 8f93490..0000000 --- a/blackhole.py +++ /dev/null @@ -1,278 +0,0 @@ -#include -#include -#include -#include -from stdint import * -import vipermath -import t, c - - -W: t.CDefine = 900 -H: t.CDefine = 540 -MAX_STEPS: t.CDefine = 400 -ESCAPE: t.CDefine = 60.0 -DISK_IN: t.CDefine = 2.6 # 吸积盘内缘 (单位: 史瓦西半径 Rs=1) -DISK_OUT: t.CDefine = 11.0 # 吸积盘外缘 -CAM_DIST: t.CDefine = 22.0 -CAM_ELEV: t.CDefine = 9.0 # 相机仰角(度): 小角度=侧视/透镜效果最强(星际穿越). 想更俯视可调到35 -FOVF: t.CDefine = 0.55 # tan(半视场) - -# ---------------- 向量 ---------------- -class V3: - x: t.CDouble - y: t.CDouble - z: t.CDouble - - def __init__(self, x: t.CDefine, y: t.CDefine, z: t.CDefine): - self.x = x - self.y = y - self.z = z - - def __add__(self, other: 'V3') -> 'V3': - return V3(self.x + other.x, self.y + other.y, self.z + other.z) - - def __sub__(self, other: 'V3') -> 'V3': - return V3(self.x - other.x, self.y - other.y, self.z - other.z) - - def __mul__(self, other: t.CDouble) -> 'V3': - return V3(self.x * other, self.y * other, self.z * other) - - def __xor__(self, other: 'V3') -> t.CDouble: # dot - return self.x * other.x + self.y * other.y + self.z * other.z - - def cross(self, other: 'V3') -> 'V3': - return V3(self.y * other.z - self.z * other.y, self.z * other.x - self.x * other.z, self.x * other.y - self.y * other.x) - - def __len__(self) -> t.CDouble: - return vipermath.sqrt(c.Deref(self) ^ c.Deref(self)) - - def nrm(self) -> 'V3': - l = len(c.Deref(self)) # self.__len__() - return self / l if l > (1e-12) else self - - def lerp(self, other: 'V3', t: t.CDouble) -> 'V3': - return self + (other - self) * t - -def clmp(x: t.CDouble, a: t.CDouble, b: t.CDouble) -> t.CDouble: - return x if x >= a and x <= b else a if x < a else b - -def smoothstep(a: t.CDouble, b: t.CDouble, x: t.CDouble) -> t.CDouble: - t = clmp((x - a) / (b - a), 0, 1) - return t * t * (3 - 2 * t) - - - -# static inline V3 v(double x,double y,double z){V3 r={x,y,z};return r;} -# static inline V3 add(V3 a,V3 b){return v(a.x+b.x,a.y+b.y,a.z+b.z);} -# static inline V3 sub(V3 a,V3 b){return v(a.x-b.x,a.y-b.y,a.z-b.z);} -# static inline V3 scl(V3 a,double s){return v(a.x*s,a.y*s,a.z*s);} -# static inline double dot(V3 a,V3 b){return a.x*b.x+a.y*b.y+a.z*b.z;} -# static inline V3 cross(V3 a,V3 b){return v(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);} -# static inline double len(V3 a){return sqrt(dot(a,a));} -# static inline V3 nrm(V3 a){double l=len(a); return l>1e-12?scl(a,1.0/l):a;} -# static inline V3 lerp(V3 a,V3 b,double t){return add(scl(a,1-t),scl(b,t));} -# static inline double clmp(double x,double a,double b){return xb?b:x);} -# static inline double smoothstep(double a,double b,double x){double t=clmp((x-a)/(b-a),0,1);return t*t*(3-2*t);} - -# ---------------- 帧缓冲 / 相机 ---------------- -fb: UINT32PTR -CAM: V3 -FWD: V3 -RIGHT: V3 -UP: V3 -# static V3 CAM, FWD, RIGHT, UP; -gT: t.CDouble = 0.0 -# static volatile double gT = 0.0; - -def setupCamera(): - e: t.CDouble = CAM_ELEV * vipermath.U_M_PI / 180.0 - CAM = V3(CAM_DIST * vipermath.cos(e), CAM_DIST * vipermath.sin(e), 0) - FWD = (V3(0, 0, 0) - CAM).nrm() - RIGHT = (FWD.cross(V3(0,1,0))).nrm() - UP = RIGHT.cross(FWD) - -# ---------------- 哈希 / 星空 ---------------- -def hash3(x: t.CDouble, y: t.CDouble, z: t.CDouble) -> t.CDouble: - n: t.CDouble = vipermath.sin(x*127.1 + y * 311.7 + z * 74.7) * 43758.5453 - return n - vipermath.floor(n) - -def stars(d: V3) -> V3: - _c: V3 = V3(0, 0, 0) - for i in range(3): - s: t.CDouble = 80.0 + i * 90.0 - px: t.CDouble = d.x * s - py: t.CDouble = d.y * s - pz: t.CDouble = d.z * s - ix: t.CDouble = vipermath.floor(px) - iy: t.CDouble = vipermath.floor(py) - iz: t.CDouble = vipermath.floor(pz) - h: t.CDouble = hash3(ix, iy, iz) - if h > 0.991: - fx: t.CDouble = px - ix - 0.5 - fy: t.CDouble = py - iy - 0.5 - d2: t.CDouble = fx * fx + fy * fy + fz * fz - br: t.CDouble = (h-0.991) / 0.009 * vipermath.exp(-d2 * 9.0) * 1.4 - _t: t.CDouble = hash3(iy, iz, ix) - tint: V3 = V3(0.7,0.8,1.0) if (_t < 0.3) else (V3(1.0,0.8,0.6) if (_t > 0.8) else V3(1,1,1)); - _c = add(_c, scl(tint, br)) - return _c - - -# ---------------- 吸积盘着色 ---------------- -static void diskShade(V3 cp,double rr,double t,V3*emit,double*alpha){ - double tt=(rr-DISK_IN)/(DISK_OUT-DISK_IN); - double edge = smoothstep(0,0.07,tt)*smoothstep(0,0.18,1.0-tt); - double ang=atan2(cp.z,cp.x); - double w = 1.0/pow(rr,1.5); # 开普勒角速度 - double ph = ang - t*0.0011*w*9.0; # 随时间旋转 - double n = 0.5+0.5*sin(ph*5.0 - rr*1.6); - double n2 = 0.5+0.5*sin(ph*13.0 + rr*0.8 + 1.7); - double dens = (0.35+0.65*n)*(0.55+0.45*n2); - double bright = (0.45+1.7*pow(1.0-tt,1.8))*edge; - - # 相对论多普勒增亮 (一侧更亮 + 微蓝移) - V3 vdir = nrm(v(-cp.z,0,cp.x)); - double beta = 0.46/sqrt(rr); - V3 toCam = nrm(sub(CAM,cp)); - double mu = dot(vdir,toCam); - double dop = 1.0/(1.0-beta*mu); - double beam = pow(dop,3.0); - - V3 c1=v(1.0,0.92,0.68), c2=v(1.0,0.42,0.13); - V3 base=lerp(c1,c2,tt); - base.z += (dop-1.0)*0.35; base.x -= (dop-1.0)*0.05; # 蓝移微调 - - double inten = bright*dens*beam*1.25; - *emit = scl(base,inten); - *alpha = clmp(edge*dens*0.92,0,1); -} - -# ---------------- 光子测地线积分 ---------------- -static V3 trace(V3 dir){ - V3 pos=CAM, vel=dir; - V3 hvec=cross(pos,vel); - double h2=dot(hvec,hvec); # 角动量守恒 - double T=1.0; V3 col=v(0,0,0); - double t=gT; - - for(int i=0;i 黑 - if(r>ESCAPE){ col=add(col,scl(stars(nrm(vel)),T)); break; } - - double dt=clmp(r*0.08,0.03,2.2); - # RK4 (a = -1.5 h2 pos / r^5) - ACC(P) scl(P, -1.5*h2/pow(dot(P,P),2.5)) - V3 k1p=vel, k1v=ACC(pos); - V3 k2p=add(vel,scl(k1v,dt*0.5)), k2v=ACC(add(pos,scl(k1p,dt*0.5))); - V3 k3p=add(vel,scl(k2v,dt*0.5)), k3v=ACC(add(pos,scl(k2p,dt*0.5))); - V3 k4p=add(vel,scl(k3v,dt)), k4v=ACC(add(pos,scl(k3p,dt))); - V3 npos=add(pos,scl(add(add(k1p,scl(k2p,2)),add(scl(k3p,2),k4p)),dt/6.0)); - V3 nvel=add(vel,scl(add(add(k1v,scl(k2v,2)),add(scl(k3v,2),k4v)),dt/6.0)); - - # 吸积盘平面 y=0 穿越检测 - if(pos.y*npos.y<0){ - double f=pos.y/(pos.y-npos.y); - V3 cp=lerp(pos,npos,f); - double rr=sqrt(cp.x*cp.x+cp.z*cp.z); - if(rr>DISK_IN && rry0;yy1;y++) - for(int x=0;x64)NT=64; - - fb=(uint32_t*)malloc((size_t)W*H*4); - bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth=W; bmi.bmiHeader.biHeight=-H; # 顶向下 - bmi.bmiHeader.biPlanes=1; bmi.bmiHeader.biBitCount=32; bmi.bmiHeader.biCompression=BI_RGB; - setupCamera(); - - WNDCLASS wc={0}; wc.lpfnWndProc=WndProc; wc.hInstance=hI; - wc.lpszClassName="bh"; wc.hCursor=LoadCursor(0,IDC_ARROW); - RegisterClass(&wc); - RECT rc={0,0,W,H}; AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,FALSE); - HWND hwnd=CreateWindow("bh","Gargantua (ESC quit)",WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT,CW_USEDEFAULT,rc.right-rc.left,rc.bottom-rc.top,0,0,hI,0); - ShowWindow(hwnd,show); - - LARGE_INTEGER fq,t0,t1; QueryPerformanceFrequency(&fq); - DWORD start=GetTickCount(); - MSG msg; int run=1; double fps=0; DWORD ftc=0; int fcnt=0; - while(run){ - while(PeekMessage(&msg,0,0,0,PM_REMOVE)){ - if(msg.message==WM_QUIT){run=0;break;} - TranslateMessage(&msg); DispatchMessage(&msg); - } - if(!run)break; - gT=(double)(GetTickCount()-start); # <<< 传入的时间 t (毫秒) - QueryPerformanceCounter(&t0); - renderFrame(); - QueryPerformanceCounter(&t1); - HDC dc=GetDC(hwnd); - SetDIBitsToDevice(dc,0,0,W,H,0,0,0,H,fb,&bmi,DIB_RGB_COLORS); - ReleaseDC(hwnd,dc); - - fcnt++; DWORD now=GetTickCount(); - if(now-ftc>500){ fps=fcnt*1000.0/(now-ftc); fcnt=0; ftc=now; - char buf[128]; sprintf(buf,"Gargantua FPS:%.1f threads:%d",fps,NT); - SetWindowText(hwnd,buf); - } - } - free(fb); - return 0; -} \ No newline at end of file diff --git a/debug_out.txt b/debug_out.txt deleted file mode 100644 index ab6fd60..0000000 --- a/debug_out.txt +++ /dev/null @@ -1 +0,0 @@ -[ERROR] 类型 'window.InputEvent' 未在符号表中找到,严格模式下需要定义此类型 diff --git a/debug_output.txt b/debug_output.txt deleted file mode 100644 index cdcc976..0000000 --- a/debug_output.txt +++ /dev/null @@ -1 +0,0 @@ -[编译终止] 1 个文件翻译失败 diff --git a/find.py b/find.py new file mode 100644 index 0000000..1af572b --- /dev/null +++ b/find.py @@ -0,0 +1,163 @@ +""" +REPL 模式文件内容搜索工具 +支持正则或纯文本搜索,默认搜索当前目录 +""" +import os +import re +import sys + +# 硬编码排除目录 +EXCLUDE_DIRS = { + '.git', '.vs', 'node_modules', '__pycache__', '.idea', + 'miniprogram_npm', '_backup_pre_redesign', +} + +# 排除的文件扩展名 +EXCLUDE_EXTS = { + '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.bmp', + '.mp3', '.mp4', '.wav', '.avi', + '.zip', '.rar', '.7z', '.tar', '.gz', + '.exe', '.dll', '.so', '.dylib', + '.pyc', '.pyo', '.class', '.o', '.obj', + '.db', '.sqlite', '.vsidx', +} + +# 默认搜索根目录 +DEFAULT_ROOT = os.path.dirname(os.path.abspath(__file__)) + + +def should_skip(dirpath): + """判断目录是否应跳过""" + parts = dirpath.replace('\\', '/').split('/') + return any(p in EXCLUDE_DIRS for p in parts) + + +def search(pattern, root=DEFAULT_ROOT, use_regex=True, max_results=50): + """搜索文件内容""" + if use_regex: + try: + compiled = re.compile(pattern, re.IGNORECASE) + except re.error as e: + print(f' 正则语法错误: {e}') + return + + count = 0 + for dirpath, dirnames, filenames in os.walk(root): + # 就地修改 dirnames 以跳过排除目录 + dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS] + + for fname in filenames: + ext = os.path.splitext(fname)[1].lower() + if ext in EXCLUDE_EXTS: + continue + + fpath = os.path.join(dirpath, fname) + relpath = os.path.relpath(fpath, root) + try: + with open(fpath, 'r', encoding='utf-8', errors='ignore') as f: + for lineno, line in enumerate(f, 1): + line_stripped = line.rstrip('\n\r') + if use_regex: + match = compiled.search(line_stripped) + if match: + highlight = line_stripped[:match.start()] + \ + f'>>> {match.group()} <<<' + \ + line_stripped[match.end():] + print(f' {relpath}:{lineno} {highlight}') + count += 1 + else: + if pattern.lower() in line_stripped.lower(): + print(f' {relpath}:{lineno} {line_stripped}') + count += 1 + + if count >= max_results: + print(f'\n ... 已达上限 {max_results} 条,停止') + return + except (PermissionError, OSError): + continue + + if count == 0: + print(' 未找到匹配内容') + else: + print(f'\n 共 {count} 条匹配') + + +def main(): + print('=== 文件内容搜索工具 ===') + print(f'搜索根目录: {DEFAULT_ROOT}') + print(f'排除目录: {EXCLUDE_DIRS}') + print() + print('命令:') + print(' /regex 正则搜索') + print(' /text 纯文本搜索') + print(' /max 设置结果上限(默认50)') + print(' /dir 切换搜索目录') + print(' /help 显示帮助') + print(' /quit 退出') + print() + print('直接输入内容默认使用【纯文本】搜索,需要正则请加 /regex 前缀') + print() + + root = DEFAULT_ROOT + use_regex = False # 修改1:默认纯文本 + max_results = 50 + + while True: + try: + raw = input('find> ').strip() + except (EOFError, KeyboardInterrupt): + print('\n再见') + break + + if not raw: + continue + + if raw == '/quit': + print('再见') + break + + if raw == '/help': + print(' /regex 正则搜索') + print(' /text 纯文本搜索') + print(' /max 设置结果上限') + print(' /dir 切换搜索目录') + print(' /help 显示帮助') + print(' /quit 退出') + print(' 直接输入内容默认纯文本搜索') + continue + + if raw.startswith('/regex '): + pattern = raw[7:].strip() + if pattern: + search(pattern, root, use_regex=True, max_results=max_results) + continue + + if raw.startswith('/text '): + pattern = raw[6:].strip() + if pattern: + search(pattern, root, use_regex=False, max_results=max_results) + continue + + if raw.startswith('/max '): + try: + max_results = int(raw[5:].strip()) + print(f' 结果上限设为 {max_results}') + except ValueError: + print(' 请输入数字') + continue + + if raw.startswith('/dir '): + new_dir = raw[5:].strip() + if os.path.isdir(new_dir): + root = os.path.abspath(new_dir) + print(f' 搜索目录切换为: {root}') + else: + print(f' 目录不存在: {new_dir}') + continue + + # 修改2:直接输入走纯文本搜索 + search(raw, root, use_regex=False, max_results=max_results) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/includes/asm.py b/includes/asm.py index b00b1f0..ef64063 100644 --- a/includes/asm.py +++ b/includes/asm.py @@ -13,6 +13,9 @@ def hlt(): def nop(): c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY]) +def pause(): + c.Asm("pause", op=[t.ASM_DESCR.CLOBBER_MEMORY]) + def inb(port: t.CUInt16T) -> t.CUInt8T: value: t.CUInt32T c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)} diff --git a/includes/base64.py b/includes/base64.py index 87e708b..899e2a8 100644 --- a/includes/base64.py +++ b/includes/base64.py @@ -1,4 +1,3 @@ -import binascii import t, c diff --git a/includes/binascii.py b/includes/binascii.py index 68f1b02..07b8b62 100644 --- a/includes/binascii.py +++ b/includes/binascii.py @@ -1,5 +1,4 @@ import t, c -import stdint HEX_CHARS: list[t.CChar, None] = "0123456789abcdef" diff --git a/includes/stdlib.py b/includes/stdlib.py index 9b603d5..38e319f 100644 --- a/includes/stdlib.py +++ b/includes/stdlib.py @@ -3,7 +3,7 @@ import t -def malloc(size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass -def calloc(nmemb: UINT, size: UINT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass -def realloc(p: str, p2: t.CLong | t.CLong) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass \ No newline at end of file diff --git a/lib/Projectrans/Config.py b/lib/Projectrans/Config.py new file mode 100644 index 0000000..2441065 --- /dev/null +++ b/lib/Projectrans/Config.py @@ -0,0 +1,214 @@ +import os +import sys +import shutil +from lib.Projectrans.Phase1Generator import Phase1Generator +from lib.Projectrans.Phase2Translator import Phase2Translator + + +def save_sha1_map(temp_dir: str, sha1_map: dict[str, str]): + """将 SHA1 映射表保存到文件""" + map_path = os.path.join(temp_dir, '_sha1_map.txt') + with open(map_path, 'w', encoding='utf-8') as f: + for sha1, rel in sorted(sha1_map.items()): + f.write(f"{sha1}:{rel}\n") + + +def Load_sha1_map(temp_dir: str) -> dict[str, str]: + """从文件加载 SHA1 映射表""" + map_path = os.path.join(temp_dir, '_sha1_map.txt') + result = {} + if os.path.exists(map_path): + with open(map_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if ':' in line: + sha1, rel = line.split(':', 1) + result[sha1] = rel + return result + + +def Load_project_config(project_file: str) -> dict: + """从 project.json 加载配置""" + import json + with open(project_file, 'r', encoding='utf-8') as f: + return json.load(f) + + +def resolve_paths(config: dict, project_file: str) -> dict: + """将配置中的相对路径转换为绝对路径""" + project_dir = os.path.dirname(os.path.abspath(project_file)) + result = dict(config) + + def resolve(p): + if p is None: + return None + if os.path.isabs(p): + return p + return os.path.normpath(os.path.join(project_dir, p)) + + if 'source_dir' in result: + result['source_dir'] = resolve(result.get('source_dir')) + elif 'sources' in result: + resolved_sources = [] + for src in result['sources']: + if '*' in src or '?' in src: + import glob as glob_module + for matched in glob_module.glob(os.path.join(project_dir, src), recursive=True): + if os.path.isfile(matched): + resolved_sources.append(matched) + else: + resolved_sources.append(resolve(src)) + result['sources'] = [s for s in resolved_sources if os.path.isfile(s)] + + result['temp_dir'] = resolve(config.get('temp_dir')) + result['output_dir'] = resolve(config.get('output_dir')) + + if 'includes' in result: + result['includes'] = [resolve(inc) for inc in result['includes']] + + result['_project_dir'] = project_dir + return result + + +def main(): + import argparse + parser = argparse.ArgumentParser( + description='TransPyC 工程翻译器 - 基于 project.json 的两阶段翻译', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=''' +示例: + # 从 project.json 读取配置并执行(默认查找当前目录) + python ProjectTrans.py + + # 指定 project.json 文件 + python ProjectTrans.py --project ./TestProject/project.json + + # 使用命令行参数覆盖 project.json 配置 + python ProjectTrans.py --src ./src --temp ./decl --output ./out --phase all + + # 仅运行阶段一 + python ProjectTrans.py --phase 1 + + # 仅运行阶段二 + python ProjectTrans.py --phase 2 + + # 清理临时目录 + python ProjectTrans.py --clean +''' + ) + parser.add_argument('--project', help='project.json 路径(默认查找当前目录)') + parser.add_argument('--src', help='源文件目录(覆盖 project.json)') + parser.add_argument('--temp', help='声明接口临时目录(覆盖 project.json)') + parser.add_argument('--output', help='输出目录(覆盖 project.json)') + parser.add_argument('--phase', choices=['1', '2', 'all'], help='阶段: 1=生成声明, 2=翻译+编译, all=全部') + parser.add_argument('--cc', help='LLVM 编译器命令(覆盖 project.json)') + parser.add_argument('--clean', action='store_true', help='清理 output 和 temp 目录') + + args = parser.parse_args() + + project_file = args.project + if not project_file: + candidates = ['project.json', './project.json'] + for c in candidates: + if os.path.exists(c): + project_file = c + break + + if project_file and os.path.exists(project_file): + print(f"[配置] 读取: {project_file}") + config = Load_project_config(project_file) + project_dir = os.path.dirname(os.path.abspath(project_file)) + print(f"[配置] 项目目录: {project_dir}") + else: + print("[错误] 未找到 project.json,请使用 --project 指定") + sys.exit(1) + + resolved = resolve_paths(config, project_file) + src = args.src or resolved.get('source_dir') or resolved.get('sources') + temp_dir = args.temp or resolved.get('temp_dir') + output_dir = args.output or resolved.get('output_dir') + phase = args.phase or 'all' + cc_cmd = args.cc or resolved.get('compiler', {}).get('cmd', 'llc') + cc_flags = resolved.get('compiler', {}).get('flags', ['-filetype=obj']) + slice_level = resolved.get('options', {}).get('slice_level', 3) + project_include_dirs = resolved.get('includes', []) + target_triple = resolved.get('target', {}).get('triple') + target_datalayout = resolved.get('target', {}).get('datalayout') + + if isinstance(src, list): + if len(src) == 1 and os.path.isdir(src[0]): + src = src[0] + else: + src = src[0] if len(src) == 1 else os.path.dirname(os.path.commonpath(src)) if all(os.path.exists(p) for p in src) else src[0] + + print(f"[配置] 源目录: {src}") + print(f"[配置] 临时目录: {temp_dir}") + print(f"[配置] 输出目录: {output_dir}") + print(f"[配置] 阶段: {phase}") + print(f"[配置] 编译器: {cc_cmd} {' '.join(cc_flags)}") + if target_triple: + print(f"[配置] 目标三元组: {target_triple}") + if target_datalayout: + print(f"[配置] 数据布局: {target_datalayout}") + + if args.clean: + if output_dir and os.path.exists(output_dir): + for f in os.listdir(output_dir): + fpath = os.path.join(output_dir, f) + try: + if os.path.isfile(fpath) or os.path.islink(fpath): + os.remove(fpath) + elif os.path.isdir(fpath): + shutil.rmtree(fpath, ignore_errors=True) + except: + pass + print(f"[清理] output: 已清空 {output_dir}") + if temp_dir and os.path.exists(temp_dir): + for f in os.listdir(temp_dir): + fpath = os.path.join(temp_dir, f) + try: + if os.path.isfile(fpath) or os.path.islink(fpath): + os.remove(fpath) + elif os.path.isdir(fpath): + shutil.rmtree(fpath, ignore_errors=True) + except: + pass + print(f"[清理] temp: 已清空 {temp_dir}") + print("[清理] 完成") + if (not phase or phase == 'all') and not args.project: + return + + if phase in ('1', 'all'): + if isinstance(src, list): + print("[错误] 阶段一需要指定源目录,不支持文件列表") + sys.exit(1) + all_include_dirs = list(project_include_dirs) if project_include_dirs else [] + for d in Phase2Translator.INCLUDE_DIRS: + if os.path.isdir(d): + d = os.path.abspath(d) + if d not in [os.path.abspath(x) for x in all_include_dirs]: + all_include_dirs.append(d) + gen = Phase1Generator(src, temp_dir, include_dirs=all_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout) + gen.run() + save_sha1_map(temp_dir, gen.sha1_map) + + if phase in ('2', 'all'): + if not output_dir: + print("[错误] 阶段二需要指定 --output 目录") + sys.exit(1) + if not os.path.exists(temp_dir): + print(f"[错误] 声明目录不存在,请先运行阶段一: {temp_dir}") + sys.exit(1) + if isinstance(src, list): + print("[错误] 阶段二需要指定源目录,不支持文件列表") + sys.exit(1) + linker_cmd = resolved.get('linker', {}).get('cmd') + linker_flags = resolved.get('linker', {}).get('flags', []) + linker_output = resolved.get('linker', {}).get('output') + target_triple = resolved.get('target', {}).get('triple') + target_datalayout = resolved.get('target', {}).get('datalayout') + startup = resolved.get('options', {}).get('startup') + trans = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout, startup=startup) + trans.sha1_map = Load_sha1_map(temp_dir) + trans.slice_level = slice_level + trans.run() diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py new file mode 100644 index 0000000..49ad2f9 --- /dev/null +++ b/lib/Projectrans/DeclarationGenerator.py @@ -0,0 +1,747 @@ +import ast +from typing import List +from lib.includes import t + + +class DeclarationGenerator: + """从 .pyi AST 生成纯 LLVM IR 声明(不使用字符串操作)""" + + def __init__(self, struct_names=None, enum_names=None, module_sha1=None, target_triple=None, target_datalayout=None, struct_sha1_map=None, exception_names=None, typedef_map=None): + import llvmlite.ir as ir + self.ir = ir + self.module = None + self.builder = None + self._DefineConstants = {} + self.struct_names = struct_names or set() + self.enum_names = enum_names or set() + self.module_sha1 = module_sha1 + self.struct_sha1_map = struct_sha1_map or {} + self.exception_names = exception_names or set() + self.target_triple = target_triple or "x86_64-none-elf" + self.target_datalayout = target_datalayout or "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + self.typedef_map = typedef_map or {} + t.configure_platform(self.target_triple) + + def generate(self, pyi_content: str, src_path: str) -> str: + import ast + tree = ast.parse(pyi_content) + + self._DefineConstants = {} + self._pyi_tree = tree + global_typedef_map = self.typedef_map + self.typedef_map = {} + if global_typedef_map: + self.typedef_map.update(global_typedef_map) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + var_name = node.target.id + if node.value and isinstance(node.value, ast.Constant): + self._DefineConstants[var_name] = node.value.value + elif node.value and isinstance(node.value, ast.Name): + self._DefineConstants[var_name] = node.value.id + is_typedef = False + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': + is_typedef = True + elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': + is_typedef = True + elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': + is_typedef = True + if is_typedef: + if node.value: + self.typedef_map[var_name] = node.value + elif isinstance(node.annotation, ast.BinOp) and node.annotation.right: + self.typedef_map[var_name] = node.annotation.right + + lines = [] + lines.append('; ModuleID = "transpyc_decl"') + lines.append(f'target triple = "{self.target_triple}"') + lines.append(f'target datalayout = "{self.target_datalayout}"') + lines.append('') + + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.FunctionDef): + if hasattr(node, 'type_params') and node.type_params: + continue + decl = self._generate_func_decl(node) + if decl: + lines.append(decl) + elif isinstance(node, ast.AnnAssign): + decl = self._generate_global_decl(node) + if decl: + lines.append(decl) + elif isinstance(node, ast.Assign): + decl = self._generate_global_assign_decl(node) + if decl: + lines.append(decl) + elif isinstance(node, ast.ClassDef): + if hasattr(node, 'type_params') and node.type_params: + continue + decls = self._generate_class_decl(node) + lines.extend(decls) + + return '\n'.join(lines) + + def _generate_func_decl(self, node: ast.FunctionDef) -> str: + """生成函数声明""" + func_name = node.name + is_export = self._is_export_func(node) + if self.module_sha1 and not is_export: + func_name = f"{self.module_sha1}.{func_name}" + CReturnTypes = [] + if node.decorator_list: + for decorator in node.decorator_list: + if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): + if decorator.func.attr == 'CReturn': + for arg in decorator.args: + CReturnTypes.append(arg) + if node.returns: + if isinstance(node.returns, ast.Subscript) and isinstance(node.returns.value, ast.Name) and node.returns.value.id == 'tuple': + slice_node = node.returns.slice + if isinstance(slice_node, ast.Tuple): + for elt in slice_node.elts: + CReturnTypes.append(elt) + else: + CReturnTypes.append(slice_node) + if CReturnTypes: + elem_types = [self._get_type_str(rt, embedded=True) for rt in CReturnTypes] + ret_type = '{ ' + ', '.join(elem_types) + ' }' + else: + ret_type = self._get_type_str(node.returns) + if not ret_type or ret_type == 'void': + ret_type = 'void' + elif ret_type == 'i8*': + if node.returns is None: + ret_type = 'void' + + params = [] + for arg in node.args.args: + if arg.annotation: + arg_type = self._get_type_str(arg.annotation) + else: + arg_type = 'i8*' + if arg_type and arg_type != 'void': + params.append(arg_type) + + param_str = ', '.join(params) if params else '' + if node.args.vararg: + param_str = param_str + ', ...' if param_str else '...' + if func_name[0].isdigit(): + return f'declare {ret_type} @"{func_name}"({param_str})' + return f'declare {ret_type} @{func_name}({param_str})' + + def _is_export_func(self, node: ast.FunctionDef) -> bool: + """检查函数是否标记为 CExport""" + if not node.returns: + return False + return self._check_annotation_for_export(node.returns) + + def _check_annotation_for_export(self, annotation) -> bool: + """递归检查类型注解中是否包含 CExport 或 t.State""" + if isinstance(annotation, ast.Attribute): + if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'State'): + return True + elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + return self._check_annotation_for_export(annotation.left) or self._check_annotation_for_export(annotation.right) + elif isinstance(annotation, ast.Name): + return annotation.id in ('CExport', 'State') + return False + + def _generate_global_decl(self, node: ast.AnnAssign) -> str: + """生成全局变量声明""" + if not isinstance(node.target, ast.Name): + return None + var_name = node.target.id + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CDefine': + return None + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': + return None + if isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': + return None + if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': + return None + if isinstance(node.annotation, ast.List): + for elt in node.annotation.elts: + if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'): + return None + if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Attribute) and isinstance(elt.value.value, ast.Name) and elt.value.value.id == 't' and elt.value.attr == 'Callable': + return None + VarType = self._get_type_str(node.annotation) + if VarType.startswith('[0 x ') and node.value and isinstance(node.value, ast.List): + elem_type = VarType[5:-1] + actual_count = len(node.value.elts) + if actual_count > 0: + VarType = f'[{actual_count} x {elem_type}]' + return f'@{var_name} = external global {VarType}' + + def _generate_global_assign_decl(self, node: ast.Assign) -> str: + """从无类型标注赋值推断并生成全局变量声明""" + if not node.targets or not isinstance(node.targets[0], ast.Name): + return None + var_name = node.targets[0].id + VarType = self._infer_type(node.value) + if VarType: + return f'@{var_name} = external global {VarType}' + return None + + def _generate_class_decl(self, node: ast.ClassDef) -> List[str]: + """生成结构体/类声明""" + decls = [] + class_name = node.name + is_enum = False + is_exception = False + if node.bases: + for base in node.bases: + if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): + if base.attr == 'CEnum' or base.attr == 'Enum': + is_enum = True + break + elif base.attr == 'Exception' or base.attr in self.exception_names: + is_exception = True + break + elif isinstance(base, ast.Name) and hasattr(base, 'id'): + if base.id == 'CEnum' or base.id == 'Enum': + is_enum = True + break + elif base.id == 'Exception' or base.id in self.exception_names: + is_exception = True + break + if is_exception: + return decls + if is_enum: + enum_values = {} + next_value = 0 + for item in node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + var_name = item.target.id + if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): + enum_values[var_name] = item.value.value + else: + enum_values[var_name] = next_value + next_value += 1 + elif isinstance(item, ast.Assign) and len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): + var_name = item.targets[0].id + if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): + enum_values[var_name] = item.value.value + next_value = item.value.value + 1 + else: + enum_values[var_name] = next_value + next_value += 1 + for var_name, value in enum_values.items(): + decls.append(f'@__config_{class_name}_{var_name} = external global i32') + return decls + member_types = [] + has_bitfield = False + total_bits = 0 + has_methods = any(isinstance(item, ast.FunctionDef) for item in node.body) + is_cvtable = False + is_cpython_object = False + if hasattr(node, 'decorator_list') and node.decorator_list: + for decorator in node.decorator_list: + if isinstance(decorator, ast.Attribute): + if getattr(decorator.value, 'id', None) == 't': + if decorator.attr == 'CVTable': + is_cvtable = True + elif decorator.attr == 'Object': + is_cpython_object = True + elif isinstance(decorator, ast.Name): + if decorator.id == 'CVTable': + is_cvtable = True + elif decorator.id == 'Object': + is_cpython_object = True + if has_methods and not is_cpython_object: + is_cpython_object = True + has_parent_class = False + for base in node.bases: + base_name = None + if isinstance(base, ast.Attribute): + base_name = base.attr + elif isinstance(base, ast.Name): + base_name = base.id + elif isinstance(base, ast.Subscript): + if isinstance(base.value, ast.Attribute): + base_name = base.value.attr + elif isinstance(base.value, ast.Name): + base_name = base.value.id + if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + has_parent_class = True + break + if has_parent_class and not is_cvtable: + is_cvtable = True + base_has_vtable = False + for base in node.bases: + base_name = None + if isinstance(base, ast.Attribute): + base_name = base.attr + elif isinstance(base, ast.Name): + base_name = base.id + elif isinstance(base, ast.Subscript): + if isinstance(base.value, ast.Attribute): + base_name = base.value.attr + elif isinstance(base.value, ast.Name): + base_name = base.value.id + if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + for n in ast.iter_child_nodes(self._pyi_tree): + if isinstance(n, ast.ClassDef) and n.name == base_name: + if hasattr(n, 'decorator_list') and n.decorator_list: + for dec in n.decorator_list: + if isinstance(dec, ast.Attribute) and getattr(dec.value, 'id', None) == 't' and dec.attr == 'CVTable': + base_has_vtable = True + elif isinstance(dec, ast.Name) and dec.id == 'CVTable': + base_has_vtable = True + break + if base_has_vtable: + break + if has_methods and is_cvtable and not base_has_vtable: + member_types.append('i8*') + seen_member_names = set() + for base in node.bases: + base_name = None + if isinstance(base, ast.Attribute): + base_name = base.attr + elif isinstance(base, ast.Name): + base_name = base.id + elif isinstance(base, ast.Subscript): + if isinstance(base.value, ast.Attribute): + base_name = base.value.attr + elif isinstance(base.value, ast.Name): + base_name = base.value.id + if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + base_member_types, base_seen = self._get_inherited_members(base_name) + for mt in base_member_types: + member_types.append(mt) + seen_member_names.update(base_seen) + for item in node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + seen_member_names.add(item.target.id) + init_members = [] + for item in node.body: + if isinstance(item, ast.FunctionDef) and item.name == '__init__': + for stmt in item.body: + if (isinstance(stmt, ast.AnnAssign) + and isinstance(stmt.target, ast.Attribute) + and isinstance(stmt.target.value, ast.Name) + and stmt.target.value.id == 'self'): + init_members.append(stmt) + untyped_self_members = [] + for m_name in [m.attr for m in init_members if isinstance(m.target, ast.Attribute)]: + seen_member_names.add(m_name) + for item in node.body: + if isinstance(item, ast.FunctionDef): + if hasattr(item, 'type_params') and item.type_params: + continue + for stmt in item.body: + if (isinstance(stmt, ast.Assign) + and len(stmt.targets) == 1 + and isinstance(stmt.targets[0], ast.Attribute) + and isinstance(stmt.targets[0].value, ast.Name) + and stmt.targets[0].value.id == 'self'): + attr_name = stmt.targets[0].attr + if attr_name not in seen_member_names: + seen_member_names.add(attr_name) + untyped_self_members.append(stmt) + for item in list(node.body) + init_members + untyped_self_members: + if isinstance(item, ast.AnnAssign): + bit_width = self._get_bitfield_width(item.annotation) + if bit_width is not None: + has_bitfield = True + total_bits += bit_width + else: + VarType = self._get_type_str(item.annotation, embedded=True) + if (isinstance(item.annotation, ast.Subscript) + and isinstance(item.annotation.value, ast.Name) + and item.annotation.value.id == 'list'): + slice_node = item.annotation.slice + is_dynamic = False + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: + count_node = slice_node.elts[1] + if isinstance(count_node, ast.Constant) and count_node.value is None: + is_dynamic = True + elif not (isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0): + if not isinstance(count_node, (ast.Name, ast.BinOp)): + is_dynamic = True + elif not isinstance(slice_node, ast.Tuple): + is_dynamic = True + if is_dynamic: + elem_type = self._get_type_str(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0], embedded=True) + init_len = 0 + if isinstance(item.value, ast.List): + init_len = len(item.value.elts) + elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): + init_len = len(item.value.value) + 1 + VarType = f'[{init_len} x {elem_type}]' + member_types.append(VarType) + elif isinstance(item, ast.Assign): + if (len(item.targets) == 1 + and isinstance(item.targets[0], ast.Attribute) + and isinstance(item.targets[0].value, ast.Name) + and item.targets[0].value.id == 'self'): + attr_name = item.targets[0].attr + if attr_name in seen_member_names: + continue + InferredType = 'i32' + if item.value and isinstance(item.value, ast.Constant): + if isinstance(item.value.value, float): + InferredType = 'float' + elif isinstance(item.value.value, bool): + InferredType = 'i8' + elif isinstance(item.value.value, str): + InferredType = 'i8*' + member_types.append(InferredType) + else: + member_types.append('i32') + if has_bitfield: + if total_bits <= 8: + member_types.insert(0, 'i8') + elif total_bits <= 16: + member_types.insert(0, 'i16') + elif total_bits <= 32: + member_types.insert(0, 'i32') + else: + member_types.insert(0, 'i64') + struct_type_name = f'%"{self.module_sha1}.{class_name}"' if self.module_sha1 else f'%struct.{class_name}' + struct_decl = f'{struct_type_name} = type {{ {", ".join(member_types)} }}' + decls.append(struct_decl) + if is_cpython_object or is_cvtable: + new_func_name = f'{class_name}.__before_init__' + if self.module_sha1: + new_func_name = f"{self.module_sha1}.{new_func_name}" + if new_func_name[0].isdigit(): + new_func_decl = f'declare void @"{new_func_name}"({struct_type_name}*)' + else: + new_func_decl = f'declare void @{new_func_name}({struct_type_name}*)' + decls.append(new_func_decl) + for item in node.body: + if isinstance(item, ast.FunctionDef): + if hasattr(item, 'type_params') and item.type_params: + continue + method_name = f'{class_name}.{item.name}' + if self.module_sha1: + method_name = f"{self.module_sha1}.{method_name}" + ret_type = self._get_type_str(item.returns) if item.returns else 'void' + if not ret_type: + ret_type = 'void' + params = [] + for arg_idx, arg in enumerate(item.args.args): + if arg.annotation: + arg_type = self._get_type_str(arg.annotation) + elif arg_idx == 0 and arg.arg == 'self': + arg_type = f'{struct_type_name}*' + else: + arg_type = 'i8*' + params.append(arg_type) + param_str = ', '.join(params) if params else '' + if method_name[0].isdigit(): + decls.append(f'declare {ret_type} @"{method_name}"({param_str})') + else: + decls.append(f'declare {ret_type} @{method_name}({param_str})') + return decls + + def _get_inherited_members(self, base_name: str): + import ast + member_types = [] + seen_names = set() + if not hasattr(self, '_pyi_tree') or self._pyi_tree is None: + return member_types, seen_names + base_node = None + for node in ast.iter_child_nodes(self._pyi_tree): + if isinstance(node, ast.ClassDef) and node.name == base_name: + base_node = node + break + if base_node is None: + return member_types, seen_names + base_decls = self._generate_class_decl(base_node) + for decl in base_decls: + if '= type {' in decl: + type_body = decl.split('= type {')[1].rstrip('}').strip() + if type_body: + for t in type_body.split(','): + t = t.strip() + if t: + member_types.append(t) + break + for item in base_node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + seen_names.add(item.target.id) + elif isinstance(item, ast.Assign) and len(item.targets) == 1: + if isinstance(item.targets[0], ast.Attribute) and isinstance(item.targets[0].value, ast.Name) and item.targets[0].value.id == 'self': + seen_names.add(item.targets[0].attr) + for item in base_node.body: + if isinstance(item, ast.FunctionDef) and item.name == '__init__': + for stmt in item.body: + if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Attribute) and isinstance(stmt.target.value, ast.Name) and stmt.target.value.id == 'self': + seen_names.add(stmt.target.attr) + elif isinstance(stmt, ast.Assign) and len(stmt.targets) == 1 and isinstance(stmt.targets[0], ast.Attribute) and isinstance(stmt.targets[0].value, ast.Name) and stmt.targets[0].value.id == 'self': + seen_names.add(stmt.targets[0].attr) + return member_types, seen_names + + @staticmethod + def _ctype_name_to_llvm(name: str) -> str: + """根据 CType 元属性自动推导 LLVM IR 类型 + + 通过 CTypeRegistry.NameToLLVM 查询,利用 CType 的 + position/IsSigned/Size 元属性自动推导,无需手动映射表。 + """ + from lib.includes.t import CTypeRegistry + result = CTypeRegistry.NameToLLVM(name) + return result + + def _get_type_str(self, annotation: ast.AST, embedded: bool = False) -> str: + import ast + from lib.includes.t import CTypeRegistry + if annotation is None: + return 'i8*' + + non_struct_types = {'list', 'dict', 'tuple', 'set', 'array'} + + if isinstance(annotation, ast.Name): + if annotation.id == 'None': + return 'void' + if annotation.id in ('str', 'bytes'): + return 'i8*' + llvm_type = CTypeRegistry.NameToLLVM(annotation.id) + if llvm_type is not None: + return llvm_type + resolved = CTypeRegistry.ResolveName(annotation.id) + if resolved is not None: + ctype_cls, ptr_level = resolved + base = CTypeRegistry.CTypeToLLVM(ctype_cls) + if ptr_level > 0: + if base == 'void': + return 'i8*' + if '*' in base: + return base + return f'{base}*' + return base + if annotation.id in non_struct_types: + return 'i32' + if annotation.id in self.enum_names: + return 'i32' + if annotation.id in self.struct_names: + sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) + sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' + if embedded: + return sname + else: + return f'{sname}*' + if annotation.id in self.typedef_map: + resolved = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded) + return resolved + sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) + sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' + return f'{sname}*' + elif isinstance(annotation, ast.Attribute): + attr_name = annotation.attr if hasattr(annotation, 'attr') else '' + module_name = '' + if hasattr(annotation, 'value'): + if isinstance(annotation.value, ast.Name): + module_name = annotation.value.id + elif isinstance(annotation.value, ast.Attribute) and hasattr(annotation.value, 'attr'): + module_name = annotation.value.attr + if (module_name == 't' and attr_name == 'State') or attr_name == 'State': + return '' + if (module_name == 't' and attr_name == 'Callable') or attr_name == 'Callable': + return 'i8*' + llvm_type = CTypeRegistry.NameToLLVM(attr_name) + if llvm_type is not None: + return llvm_type + resolved = CTypeRegistry.ResolveName(attr_name) + if resolved is not None: + ctype_cls, ptr_level = resolved + base = CTypeRegistry.CTypeToLLVM(ctype_cls) + if ptr_level > 0: + if base == 'void': + return 'i8*' + if '*' in base: + return base + return f'{base}*' + return base + if attr_name in self.typedef_map: + return self._get_type_str(self.typedef_map[attr_name], embedded=embedded) + if attr_name in self.enum_names: + return 'i32' + if attr_name in self.struct_names: + sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + if embedded: + return sname + else: + return f'{sname}*' + if attr_name and attr_name[0].isupper() and attr_name not in non_struct_types: + sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + return f'{sname}*' + if attr_name and attr_name not in non_struct_types: + sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + return f'{sname}*' + return 'i32' + elif isinstance(annotation, ast.BinOp): + left_type = self._get_type_str(annotation.left, embedded=embedded) + right_type = self._get_type_str(annotation.right, embedded=embedded) + if left_type in ('', 'void'): + return right_type if right_type not in ('', 'void') else (left_type or right_type) + if right_type in ('', 'void'): + return left_type + if '*' in left_type: + return left_type + if '*' in right_type: + if right_type == 'i8*': + return self._type_to_llvm_ptr(left_type) + return right_type + return left_type + elif isinstance(annotation, ast.Subscript): + base = self._get_type_str(annotation.value) + if base == 'i8*' and isinstance(annotation.slice, ast.Constant): + return f'[{self._get_const_int(annotation.slice)} x i8]' + if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): + return f'[{annotation.slice.value} x {base}]' + if isinstance(annotation.value, ast.Name) and annotation.value.id == 'list': + slice_node = annotation.slice + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: + elem_type = self._get_type_str(slice_node.elts[0], embedded=True) + count_node = slice_node.elts[1] + array_count = self._get_const_int(count_node) + if array_count > 0: + return f'[{array_count} x {elem_type}]' + else: + return f'[0 x {elem_type}]' + elem_type = self._get_type_str(slice_node, embedded=True) + return f'[0 x {elem_type}]' + if isinstance(annotation.value, ast.Name) and annotation.value.id == 'tuple': + slice_node = annotation.slice + if isinstance(slice_node, ast.Tuple): + elem_types = [self._get_type_str(e, embedded=True) for e in slice_node.elts] + else: + elem_types = [self._get_type_str(slice_node, embedded=True)] + return '{ ' + ', '.join(elem_types) + ' }' + return f'{base}' + elif isinstance(annotation, ast.Constant): + if annotation.value is None: + return 'void' + if isinstance(annotation.value, int): + return 'i32' + if isinstance(annotation.value, str): + type_name = annotation.value + if type_name in self.enum_names: + return 'i32' + if type_name in self.struct_names: + sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) + sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' + if embedded: + return sname + else: + return f'{sname}*' + llvm_type = CTypeRegistry.NameToLLVM(type_name) + if llvm_type is not None: + return llvm_type + resolved = CTypeRegistry.ResolveName(type_name) + if resolved is not None: + ctype_cls, ptr_level = resolved + base = CTypeRegistry.CTypeToLLVM(ctype_cls) + if ptr_level > 0: + if base == 'void': + return 'i8*' + if '*' in base: + return base + return f'{base}*' + return base + sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) + sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' + return f'{sname}*' + return 'i8*' + elif isinstance(annotation, ast.Call): + if isinstance(annotation.func, ast.Name) and annotation.func.id == 'callable': + return 'i8*' + if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Callable': + return 'i8*' + return 'i32' + + def _type_to_llvm_ptr(self, type_str: str) -> str: + if type_str.startswith('%struct.') and not type_str.endswith('*'): + return type_str + '*' + if type_str.startswith('%') and not type_str.endswith('*'): + return type_str + '*' + if type_str.endswith('*'): + return type_str + from lib.includes.t import CTypeRegistry + resolved = CTypeRegistry.ResolveName(type_str) + if resolved is not None: + ctype_cls, ptr_level = resolved + llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str: + return f'{llvm_str}{"*" * (ptr_level + 1)}' + cnameres = CTypeRegistry.CNameToClass(type_str) + if cnameres is not None: + llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) + if llvm_str: + return f'{llvm_str}*' + return f'{type_str}*' + + def _infer_type(self, value: ast.AST) -> str: + """从值推断类型""" + import ast + if isinstance(value, ast.Constant): + if isinstance(value.value, int): + return 'i32' + elif isinstance(value.value, float): + return 'double' + elif isinstance(value.value, str): + return 'i8*' + elif isinstance(value.value, bool): + return 'i8' + elif isinstance(value, ast.List): + return 'i8*' + elif isinstance(value, ast.Dict): + return 'i8*' + elif isinstance(value, ast.Name): + return 'i32' + elif isinstance(value, ast.BinOp): + return self._infer_type(value.left) + elif isinstance(value, ast.Call): + return 'i8*' + return 'i32' + + def _get_bitfield_width(self, annotation: ast.AST): + import ast + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + right_width = self._get_bitfield_width(annotation.right) + if right_width is not None: + return right_width + return self._get_bitfield_width(annotation.left) + if isinstance(annotation, ast.Call): + if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Bit': + if annotation.args: + arg = annotation.args[0] + if isinstance(arg, ast.Constant) and isinstance(arg.value, int): + return arg.value + if isinstance(annotation, ast.Subscript): + if isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'Bit': + if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): + return annotation.slice.value + return None + + def _get_const_int(self, node: ast.AST) -> int: + """获取常量整数值,支持符号常量和简单表达式""" + import ast + if isinstance(node, ast.Constant) and isinstance(node.value, int): + return node.value + if isinstance(node, ast.Name): + if node.id in self._DefineConstants: + val = self._DefineConstants[node.id] + if isinstance(val, int): + return val + if isinstance(node, ast.BinOp): + left_val = self._get_const_int(node.left) + right_val = self._get_const_int(node.right) + if left_val and right_val: + if isinstance(node.op, ast.Add): + return left_val + right_val + if isinstance(node.op, ast.Sub): + return left_val - right_val + if isinstance(node.op, ast.Mult): + return left_val * right_val + if isinstance(node.op, ast.Div): + return left_val // right_val + if isinstance(node.op, ast.FloorDiv): + return left_val // right_val + return 0 diff --git a/lib/Projectrans/Phase1Generator.py b/lib/Projectrans/Phase1Generator.py new file mode 100644 index 0000000..bc3319e --- /dev/null +++ b/lib/Projectrans/Phase1Generator.py @@ -0,0 +1,338 @@ +import os +import ast +import traceback +from lib.Projectrans.Utils import compute_sha1, get_file_dependencies, find_reachable_files_from_entries +from lib.Projectrans.DeclarationGenerator import DeclarationGenerator +from StubGen import PythonToStubConverter + + +class Phase1Generator: + """阶段一:从源文件生成声明接口""" + + def __init__(self, src_root: str, temp_dir: str, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None): + self.src_root = os.path.abspath(src_root) + self.temp_dir = os.path.abspath(temp_dir) + self.include_dirs = include_dirs or [] + self.sha1_map: dict[str, str] = {} + self.include_py_map: dict[str, str] = {} + self.entry_files = entry_files + self.target_triple = target_triple + self.target_datalayout = target_datalayout + os.makedirs(self.temp_dir, exist_ok=True) + + def _get_needed_include_files(self, reachable_source_files: set) -> list: + """从可达源文件收集所有被引用(含传递依赖)的 include 文件""" + include_file_map = {} + for includes_dir in self.include_dirs: + if not os.path.isdir(includes_dir): + continue + for root, dirs, files in os.walk(includes_dir): + dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] + for fname in files: + if fname.endswith('.py') or fname.endswith('.pyi'): + src_path = os.path.join(root, fname) + rel_from_inc = os.path.relpath(src_path, includes_dir) + ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name = os.path.splitext(ModulePath)[0] + info = (src_path, rel_from_inc, includes_dir) + include_file_map[module_name] = info + top_pkg = module_name.split('.')[0] + if top_pkg not in include_file_map: + include_file_map[top_pkg] = info + + imported_from_src = set() + for src_path in reachable_source_files: + deps = get_file_dependencies(src_path, self.src_root) + imported_from_src.update(deps) + + needed = set() + queue = list(imported_from_src) + while queue: + mod_name = queue.pop(0) + if mod_name in needed: + continue + if mod_name in include_file_map: + needed.add(mod_name) + src_path = include_file_map[mod_name][0] + includes_dir = include_file_map[mod_name][2] + deps = get_file_dependencies(src_path, includes_dir) + for dep in deps: + if dep in include_file_map and dep not in needed: + queue.append(dep) + + needed_infos = [] + for mod_name in sorted(needed): + if mod_name in include_file_map: + info = include_file_map[mod_name] + if info not in needed_infos: + needed_infos.append(info) + + return needed_infos + + def run(self): + """扫描源目录,只处理入口文件可达的 .py 文件(导入遍历)""" + if self.entry_files: + py_files = list(self.entry_files) + else: + main_py = os.path.join(self.src_root, 'main.py') + if os.path.exists(main_py): + py_files = [main_py] + else: + py_files = [] + for root, dirs, files in os.walk(self.src_root): + dirs[:] = [d for d in dirs if d not in ('__pycache__',)] + for file in files: + if file.endswith('.py'): + py_files.append(os.path.join(root, file)) + + if not py_files: + print("[阶段一] 未找到入口文件或源文件") + return + + if self.entry_files: + reachable = find_reachable_files_from_entries(self.src_root, py_files) + else: + reachable = find_reachable_files_from_entries(self.src_root, py_files) + + print(f"[阶段一] 找到 {len(reachable)} 个可达源文件(从入口遍历)") + + for i, src_path in enumerate(sorted(reachable), 1): + rel = os.path.relpath(src_path, self.src_root) + print(f"[{i}/{len(reachable)}] 生成签名: {rel}") + try: + self._process_file_pyi(src_path, rel) + except Exception as e: + print(f" [错误] {e}") + traceback.print_exc() + + needed_includes = self._get_needed_include_files(reachable) + self._process_include_py_files_pyi(needed_includes) + + struct_names, enum_names, struct_sha1_map, exception_names = self._build_struct_registry() + print(f"\n[阶段一] 结构体注册表: {len(struct_names)} 个类型, {len(enum_names)} 个枚举") + for name in sorted(struct_names): + print(f" {name}") + + for i, src_path in enumerate(sorted(reachable), 1): + rel = os.path.relpath(src_path, self.src_root) + try: + self._process_file_stub(src_path, rel, struct_names, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) + except Exception as e: + print(f" [错误] {e}") + traceback.print_exc() + + self._process_include_py_files_stub(struct_names, needed_includes, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) + + print(f"\n[阶段一完成] 声明接口生成到: {self.temp_dir}") + print(f"SHA1 映射表 ({len(self.sha1_map)} 个文件):") + for sha1, rel in sorted(self.sha1_map.items()): + print(f" {sha1} -> {rel}") + + def _collect_include_py_files(self): + include_py_files = [] + for includes_dir in self.include_dirs: + if not os.path.isdir(includes_dir): + continue + for root, dirs, files in os.walk(includes_dir): + dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] + for fname in files: + if fname.endswith('.py') or fname.endswith('.pyi'): + src_path = os.path.join(root, fname) + rel_from_inc = os.path.relpath(src_path, includes_dir) + include_py_files.append((src_path, rel_from_inc, includes_dir)) + return include_py_files + + def _process_include_py_files_pyi(self, needed_includes: list = None): + if needed_includes is not None: + include_py_files = needed_includes + else: + include_py_files = self._collect_include_py_files() + if not include_py_files: + return + print(f"\n[阶段一-includes] 处理 {len(include_py_files)} 个被引用的 Python 库文件") + for src_path, rel_from_inc, includes_dir in include_py_files: + ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name = os.path.splitext(ModulePath)[0] + try: + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + sha1 = compute_sha1(content) + self.sha1_map[sha1] = f"includes/{rel_from_inc}" + top_module = rel_from_inc.split(os.sep)[0].split('/')[0] + if top_module not in self.include_py_map: + self.include_py_map[top_module] = sha1 + self.include_py_map[module_name] = sha1 + + sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + if os.path.isfile(sig_path): + print(f" 缓存命中: {rel_from_inc} -> {sha1}.pyi") + continue + + sig_content = PythonToStubConverter.convert(content, module_name) + with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(sig_content) + print(f" 生成签名: {rel_from_inc} -> {sha1}.pyi") + except Exception as e: + print(f" [错误] {rel_from_inc}: {e}") + + def _collect_typedef_map(self): + import ast as _ast + typedef_map = {} + if not os.path.isdir(self.temp_dir): + return typedef_map + for fname in os.listdir(self.temp_dir): + if not fname.endswith('.pyi'): + continue + pyi_path = os.path.join(self.temp_dir, fname) + try: + with open(pyi_path, 'r', encoding='utf-8') as f: + content = f.read() + tree = _ast.parse(content) + for node in _ast.iter_child_nodes(tree): + if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): + var_name = node.target.id + is_typedef = False + if isinstance(node.annotation, _ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': + is_typedef = True + elif isinstance(node.annotation, _ast.Name) and node.annotation.id == 'CTypedef': + is_typedef = True + elif isinstance(node.annotation, _ast.BinOp) and isinstance(node.annotation.left, _ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': + is_typedef = True + if is_typedef and node.value and var_name not in typedef_map: + typedef_map[var_name] = node.value + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"收集 typedef 映射失败: {_e}", "Exception") + return typedef_map + + def _process_include_py_files_stub(self, struct_names: set, needed_includes: list = None, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): + if needed_includes is not None: + include_py_files = needed_includes + else: + include_py_files = self._collect_include_py_files() + if not include_py_files: + return + typedef_map = self._collect_typedef_map() + for src_path, rel_from_inc, includes_dir in include_py_files: + ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name = os.path.splitext(ModulePath)[0] + try: + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + sha1 = compute_sha1(content) + + stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") + if os.path.isfile(stub_path): + print(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll") + continue + + sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + with open(sig_path, 'r', encoding='utf-8') as f: + sig_content = f.read() + + self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) + print(f" 生成声明: {rel_from_inc} -> {sha1}.stub.ll") + except Exception as e: + print(f" [错误] {rel_from_inc}: {e}") + + def _process_file_pyi(self, src_path: str, rel_path: str): + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + + sha1 = compute_sha1(content) + self.sha1_map[sha1] = rel_path + + sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + if os.path.isfile(sig_path): + print(f" -> {sha1}.pyi (缓存)") + return + + module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + sig_content = PythonToStubConverter.convert(content, module_name) + with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(sig_content) + print(f" -> {sha1}.pyi (签名)") + + def _process_file_stub(self, src_path: str, rel_path: str, struct_names: set, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + + sha1 = compute_sha1(content) + stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") + if os.path.isfile(stub_path): + print(f" -> {sha1}.stub.ll (缓存)") + return + + sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + with open(sig_path, 'r', encoding='utf-8') as f: + sig_content = f.read() + + typedef_map = self._collect_typedef_map() + self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) + print(f" -> {sha1}.stub.ll (声明)") + + def _build_struct_registry(self): + struct_names = set() + enum_names = set() + exception_names = set() + struct_sha1_map = {} + valid_sha1_keys = set(self.sha1_map.keys()) + for fname in os.listdir(self.temp_dir): + if not fname.endswith('.pyi'): + continue + sha1_key = fname.replace('.pyi', '') + if sha1_key not in valid_sha1_keys: + continue + pyi_path = os.path.join(self.temp_dir, fname) + try: + with open(pyi_path, 'r', encoding='utf-8') as f: + content = f.read() + tree = ast.parse(content) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.ClassDef): + is_enum = False + is_exception = False + if node.bases: + for base in node.bases: + if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): + if base.attr in ('CEnum', 'Enum'): + is_enum = True + break + elif base.attr == 'Exception' or base.attr in exception_names: + is_exception = True + break + elif isinstance(base, ast.Name) and hasattr(base, 'id'): + if base.id in ('CEnum', 'Enum'): + is_enum = True + break + elif base.id == 'Exception' or base.id in exception_names: + is_exception = True + break + if is_enum: + enum_names.add(node.name) + elif is_exception: + exception_names.add(node.name) + else: + struct_names.add(node.name) + struct_sha1_map[node.name] = sha1_key + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"构建结构体/枚举注册表失败: {_e}", "Exception") + return struct_names, enum_names, struct_sha1_map, exception_names + + def _generate_decl_ll(self, pyi_content: str, ll_path: str, src_path: str, struct_names: set = None, enum_names: set = None, module_sha1: str = None, struct_sha1_map: dict = None, exception_names: set = None, typedef_map: dict = None): + try: + decl_gen = DeclarationGenerator(struct_names=struct_names, enum_names=enum_names, module_sha1=module_sha1, target_triple=self.target_triple, target_datalayout=self.target_datalayout, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) + decl_ll = decl_gen.generate(pyi_content, src_path) + with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(decl_ll) + except Exception as e: + print(f" [警告] .ll 声明生成失败: {e}") + with open(ll_path, 'w', encoding='utf-8') as f: + f.write(f"; declaration for {os.path.basename(src_path)}\n; error: {e}\n") diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py new file mode 100644 index 0000000..61d7eab --- /dev/null +++ b/lib/Projectrans/Phase2Translator.py @@ -0,0 +1,2423 @@ +import sys +import os +import re +import shutil +import subprocess +import ast +import traceback +import json +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.includes import t +from lib.Projectrans.Utils import compute_sha1, _check_annotation_for_export, find_reachable_files_from_entries, topological_sort_files +import TransPyC +from StubGen import PythonToStubConverter + + +def _parallel_translate_worker(src_path, out_path, src_root, temp_dir, output_dir, + include_dirs, triple, datalayout, sha1_map, sig_files, + stub_files, include_py_map, slice_level, + shared_sym_pickle_path, struct_sha1_map): + try: + import pickle + from lib.Projectrans import Phase2Translator + from lib.Projectrans.Utils import compute_sha1 + trans = Phase2Translator(src_root, temp_dir, output_dir, + compile_cmd='llc', include_dirs=include_dirs, + target_triple=triple, target_datalayout=datalayout) + trans.sha1_map = sha1_map + trans.sig_files = sig_files + trans.stub_files = stub_files + trans.include_py_map = include_py_map + trans.slice_level = slice_level + trans.struct_sha1_map = struct_sha1_map + + if shared_sym_pickle_path and os.path.exists(shared_sym_pickle_path): + with open(shared_sym_pickle_path, 'rb') as f: + shared_data = pickle.load(f) + trans._shared_symbol_table = shared_data['symbol_table'] + trans._shared_source_module_sig_files = shared_data['source_module_sig_files'] + trans._shared_all_dc = shared_data['all_dc'] + trans._shared_export_extern_funcs = shared_data['export_extern_funcs'] + trans.inline_func_symbols = shared_data['inline_func_symbols'] + trans.function_default_args = shared_data['function_default_args'] + trans._shared_generic_class_templates = shared_data.get('generic_class_templates', {}) + else: + trans._precollect_inline_symbols() + trans._build_shared_symbol_data() + + trans._translate_file(src_path, out_path) + return ('ok', src_path, '') + except Exception as e: + import traceback + return ('error', src_path, f'{e}\n{traceback.format_exc()}') # limit + + +class Phase2Translator: + """阶段二:使用声明接口翻译源文件""" + + INCLUDE_LIB_EXTENSIONS = ('.dll', '.ll', '.so', '.o', '.a', '.lib') + INCLUDE_SRC_EXTENSIONS = ('.c', '.cpp', '.cc', '.cxx', '.m', '.mm') + INCLUDE_DIRS = [ + os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'includes'), + r"d:\Users\TermiNexus\Desktop\TransPyC\includes", + ] + + def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list = None, linker_cmd: str = None, linker_flags: list = None, linker_output: str = None, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None, startup=None): + self.src_root = os.path.abspath(src_root) + self.temp_dir = os.path.abspath(temp_dir) + self.output_dir = os.path.abspath(output_dir) + self.compile_cmd = compile_cmd + self.compile_flags = compile_flags or ['-filetype=obj'] + self.triple = target_triple + self.datalayout = target_datalayout + if not self.triple: + for i, flag in enumerate(self.compile_flags): + if flag.startswith('-mtriple='): + self.triple = flag[len('-mtriple='):] + elif flag == '-mtriple' and i + 1 < len(self.compile_flags): + self.triple = self.compile_flags[i + 1] + self.linker_cmd = linker_cmd + self.linker_flags = linker_flags or [] + self.linker_output = linker_output + self.slice_level = 3 + self.sha1_map: dict[str, str] = {} + self.sig_files: dict[str, str] = {} + self.stub_files: dict[str, str] = {} + self.include_py_map: dict[str, str] = {} + self.used_includes: set = set() + self._last_ErrorStack = None + self.function_default_args: dict = {} + self.inline_func_symbols: dict = {} + self.extra_link_files: list = [] + self.extra_compile_files: list = [] + self.extra_py_files: list = [] + self._include_sha1s: set = set() + self.entry_files = entry_files + self.startup = startup # None | True | dict (如 {"__main": "main"}) + self._shared_symbol_table = None + self._shared_source_module_sig_files = {} + self._shared_all_dc = {} + self._shared_export_extern_funcs = set() + self._stub_decls_cache = {} + default_dirs = [d for d in self.INCLUDE_DIRS if os.path.isdir(d)] + if include_dirs: + seen = set() + self.include_dirs = [] + for d in list(include_dirs) + default_dirs: + d = os.path.abspath(d) + if d not in seen and os.path.isdir(d): + self.include_dirs.append(d) + seen.add(d) + else: + self.include_dirs = default_dirs + self._LoadSha1Map() + + def _LoadSha1Map(self): + """从 temp_dir 加载 SHA1 映射、签名文件和 stub 声明文件列表""" + if not os.path.exists(self.temp_dir): + print(f"[错误] 声明目录不存在: {self.temp_dir}") + return + + for fname in os.listdir(self.temp_dir): + fpath = os.path.join(self.temp_dir, fname) + if fname.startswith('_'): + continue + if fname.endswith('.pyi'): + sha1 = fname[:-4] + self.sig_files[sha1] = fpath + elif fname.endswith('.stub.ll'): + sha1 = fname[:-8] + self.stub_files[sha1] = fpath + + sha1_file_path = os.path.join(self.temp_dir, '_sha1_map.txt') + if os.path.exists(sha1_file_path): + with open(sha1_file_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if ':' in line: + sha1, rel = line.split(':', 1) + self.sha1_map[sha1] = rel + if rel.startswith('includes/'): + module_name = os.path.splitext(os.path.basename(rel))[0] + self.include_py_map[module_name] = sha1 + else: + for sha1, stub_path in self.stub_files.items(): + self.sha1_map[sha1] = sha1 + + def _build_struct_sha1_map(self): + struct_sha1_map = {} + valid_sha1_keys = set(self.sha1_map.keys()) + for fname in os.listdir(self.temp_dir): + if not fname.endswith('.pyi'): + continue + sha1_key = fname.replace('.pyi', '') + if sha1_key not in valid_sha1_keys: + continue + pyi_path = os.path.join(self.temp_dir, fname) + try: + with open(pyi_path, 'r', encoding='utf-8') as f: + tree = ast.parse(f.read()) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析 .pyi 签名文件失败: {_e}", "Exception") + continue + for node in ast.walk(tree): + if isinstance(node, ast.ClassDef): + struct_sha1_map[node.name] = sha1_key + return struct_sha1_map + + def run(self): + """扫描源目录,翻译并生成 .ll 含代码文件(导入遍历)""" + if self.entry_files: + py_files = list(self.entry_files) + else: + main_py = os.path.join(self.src_root, 'main.py') + if os.path.exists(main_py): + py_files = [main_py] + else: + py_files = [] + for root, dirs, files in os.walk(self.src_root): + dirs[:] = [d for d in dirs if d not in ('__pycache__',)] + for file in files: + if file.endswith('.py'): + py_files.append(os.path.join(root, file)) + + if not py_files: + print("[阶段二] 未找到入口文件或源文件") + return + + reachable = find_reachable_files_from_entries(self.src_root, py_files) + py_files = list(reachable) + + py_files = topological_sort_files(py_files, self.src_root) + + print(f"[阶段二] 找到 {len(py_files)} 个可达源文件(已按依赖排序)") + print("[阶段二] 处理顺序:") + for i, f in enumerate(py_files[:10], 1): + rel = os.path.relpath(f, self.src_root) + print(f" {i}. {rel}") + os.makedirs(self.output_dir, exist_ok=True) + + valid_sha1s = set(self.sha1_map.keys()) + old_stub_count = len(self.stub_files) + old_sig_count = len(self.sig_files) + self.stub_files = {k: v for k, v in self.stub_files.items() if k in valid_sha1s} + self.sig_files = {k: v for k, v in self.sig_files.items() if k in valid_sha1s} + if old_stub_count != len(self.stub_files) or old_sig_count != len(self.sig_files): + print(f"[阶段二] 过滤旧文件: stub {old_stub_count}->{len(self.stub_files)}, sig {old_sig_count}->{len(self.sig_files)}") + + active_sha1s = set() + self._precollect_inline_symbols() + self._build_shared_symbol_data() + self.struct_sha1_map = self._build_struct_sha1_map() + + need_translate = [] + for i, src_path in enumerate(py_files, 1): + rel = os.path.relpath(src_path, self.src_root) + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + sha1 = compute_sha1(content) + active_sha1s.add(sha1) + out_path = os.path.join(self.output_dir, f"{sha1}.ll") + + current_ModuleSha1Map = self._build_current_ModuleSha1Map(sha1) + + try: + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.Import): + for alias in node.names: + self.used_includes.add(alias.name.split('.')[0]) + elif isinstance(node, ast.ImportFrom): + if node.module: + self.used_includes.add(node.module.split('.')[0]) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"收集源文件导入的 include 模块失败: {_e}", "Exception") + + if os.path.isfile(out_path): + deps_changed = self._check_deps_changed(sha1, current_ModuleSha1Map) + if not deps_changed: + print(f"[{i}/{len(py_files)}] 跳过(缓存): {rel} -> {sha1}.ll") + continue + else: + if self._recombine_ll(sha1, current_ModuleSha1Map): + print(f"[{i}/{len(py_files)}] 重组(依赖变化): {rel} -> {sha1}.ll") + continue + print(f"[{i}/{len(py_files)}] 重译(依赖变化): {rel} -> {sha1}.ll") + + else: + stub_cache = os.path.join(self.output_dir, f"{sha1}.stub.ll") + text_cache = os.path.join(self.output_dir, f"{sha1}.text.ll") + if os.path.isfile(stub_cache) and os.path.isfile(text_cache): + if self._recombine_ll(sha1, current_ModuleSha1Map): + print(f"[{i}/{len(py_files)}] 重组(缓存恢复): {rel} -> {sha1}.ll") + continue + + need_translate.append((i, src_path, out_path, sha1, current_ModuleSha1Map)) + + if need_translate: + print(f"\n[阶段二] 需要翻译 {len(need_translate)} 个文件") + import time + t_start = time.time() + + n_workers = min(os.cpu_count() or 4, len(need_translate), 8) + + if n_workers > 1 and len(need_translate) > 1: + from concurrent.futures import ProcessPoolExecutor, as_completed + import pickle + print(f" 并行翻译 (workers={n_workers})") + + shared_pickle_path = os.path.join(self.temp_dir, '_shared_sym.pkl') + try: + shared_data = { + 'symbol_table': self._shared_symbol_table, + 'source_module_sig_files': self._shared_source_module_sig_files, + 'all_dc': self._shared_all_dc, + 'export_extern_funcs': self._shared_export_extern_funcs, + 'inline_func_symbols': self.inline_func_symbols, + 'function_default_args': self.function_default_args, + 'generic_class_templates': self._shared_generic_class_templates, + } + with open(shared_pickle_path, 'wb') as f: + pickle.dump(shared_data, f, protocol=pickle.HIGHEST_PROTOCOL) + print(f" 共享符号表已序列化 ({os.path.getsize(shared_pickle_path)//1024}KB)") + except Exception as e: + print(f" [警告] 符号表序列化失败({e}),worker将自行构建") + shared_pickle_path = '' + + errors = [] + with ProcessPoolExecutor(max_workers=n_workers) as executor: + futures = {} + for i, src_path, out_path, sha1, msm in need_translate: + rel = os.path.relpath(src_path, self.src_root) + future = executor.submit( + _parallel_translate_worker, + src_path, out_path, + self.src_root, self.temp_dir, self.output_dir, + self.include_dirs, self.triple, self.datalayout, + self.sha1_map, self.sig_files, self.stub_files, + self.include_py_map, self.slice_level, + shared_pickle_path, self.struct_sha1_map + ) + futures[future] = (i, rel) + + done_count = 0 + for future in as_completed(futures): + i, rel = futures[future] + done_count += 1 + try: + status, _, err = future.result() + if status == 'ok': + print(f" [{done_count}/{len(need_translate)}] 完成: {rel}") + else: + print(f" [错误] {rel}: {err}") + errors.append((rel, err)) + except Exception as e: + print(f" [错误] {rel}: {e}") + errors.append((rel, str(e))) + + if errors: + print(f"\n[编译终止] {len(errors)} 个文件翻译失败") + sys.exit(1) + else: + for idx, (i, src_path, out_path, sha1, msm) in enumerate(need_translate): + rel = os.path.relpath(src_path, self.src_root) + t0 = time.time() + try: + self._translate_file(src_path, out_path, prebuilt_ModuleSha1Map=msm) + t1 = time.time() + print(f" [{idx+1}/{len(need_translate)}] {rel} ({t1-t0:.1f}s)") + except Exception as e: + print(f" [错误] {rel}: {e}") + traceback.print_exc() + print(f"\n[编译终止] 翻译失败") + sys.exit(1) + t_end = time.time() + print(f" 翻译总耗时: {t_end-t_start:.1f}s") + + print(f"\n[阶段二完成] .ll 文件生成到: {self.output_dir}") + self._scan_include_libraries() + self._compile_include_py_files(active_sha1s) + self._compile_ll_files(active_sha1s) + self._compile_include_sources() + if self.linker_cmd: + self._link_obj_files(active_sha1s) + + def _build_current_ModuleSha1Map(self, self_sha1: str) -> dict: + """构建当前模块的依赖 SHA1 映射(与 _translate_file 中逻辑一致)""" + ModuleSha1Map = {} + for sha1_key, sig_path in self.sig_files.items(): + if sha1_key == self_sha1: + continue + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if rel_path.startswith('includes/'): + inc_mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + inc_mod_name = inc_mod_name[len('includes/'):] + inc_short_name = inc_mod_name.split('.')[-1] if '.' in inc_mod_name else inc_mod_name + actual_sha1 = sha1_key + for inc_dir in self.include_dirs: + if os.path.isdir(inc_dir): + py_path = os.path.join(inc_dir, rel_path[len('includes/'):].replace(os.sep, '/')) + py_path = os.path.splitext(py_path)[0] + '.py' + if os.path.isfile(py_path): + with open(py_path, 'r', encoding='utf-8') as f: + py_sha1 = compute_sha1(f.read()) + actual_sha1 = py_sha1 + break + ModuleSha1Map[inc_mod_name] = actual_sha1 + ModuleSha1Map[inc_short_name] = actual_sha1 + # Also add parent package name (e.g., 'hashlib' for 'hashlib.__init__') + if inc_short_name == '__init__' and '.' in inc_mod_name: + parent_pkg = inc_mod_name.rsplit('.', 1)[0] + ModuleSha1Map[parent_pkg] = actual_sha1 + continue + module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + ModuleSha1Map[module_name] = sha1_key + short_name = module_name.split('.')[-1] if '.' in module_name else module_name + ModuleSha1Map[short_name] = sha1_key + return ModuleSha1Map + + @staticmethod + def _split_ll(ll_content: str): + """将 .ll 内容拆分为 stub(声明)和 text(代码)两部分 + + stub: target, 注释, %type = type, declare, @xxx = external global + text: define ... { ... }, @xxx = global/constant (带初始化器) + """ + import re + stub_lines = [] + text_lines = [] + in_define = False + brace_depth = 0 + module_sha1 = None + defined_names = set() + + for line in ll_content.splitlines(True): + stripped = line.strip() + + if stripped.startswith('define '): + dm = re.match(r'define\s+[^@]*@"?([a-f0-9]+)\.', stripped) + if dm and module_sha1 is None: + module_sha1 = dm.group(1) + dm2 = re.match(r'define\s+[^@]*@"?([^"\s(]+)"?', stripped) + if dm2: + defined_names.add(dm2.group(1)) + + in_global_def = False + global_var_name = None + global_type_parts = [] + global_brace_depth = 0 + + for line in ll_content.splitlines(True): + stripped = line.strip() + + if in_global_def: + text_lines.append(line) + global_type_parts.append(stripped) + global_brace_depth += stripped.count('{') - stripped.count('}') + if global_brace_depth <= 0: + full_type = ' '.join(global_type_parts).strip() + depth = 0 + type_end = len(full_type) + for ci, cc in enumerate(full_type): + if cc in ('{', '['): + depth += 1 + elif cc in ('}', ']'): + depth -= 1 + elif depth == 0 and cc == ' ': + type_end = ci + break + var_type = full_type[:type_end].strip() + if var_type: + stub_lines.append(f'{global_var_name} = external global {var_type}\n') + in_global_def = False + global_var_name = None + global_type_parts = [] + global_brace_depth = 0 + continue + + if in_define: + text_lines.append(line) + brace_depth += stripped.count('{') - stripped.count('}') + if brace_depth <= 0: + in_define = False + continue + + if stripped.startswith('define '): + text_lines.append(line) + in_define = True + brace_depth = stripped.count('{') - stripped.count('}') + decl_line = re.sub(r'^define\s+', 'declare ', stripped) + decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) + decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) + paren_pos = decl_line.rfind(')') + if paren_pos >= 0: + decl_line = decl_line[:paren_pos + 1] + stub_lines.append(decl_line + '\n') + continue + + if stripped == '{' and text_lines and not in_define: + prev_stripped = text_lines[-1].strip() if text_lines else '' + if prev_stripped.startswith('define ') or prev_stripped.endswith('noredzone') or prev_stripped.endswith(')'): + text_lines.append(line) + brace_depth = 1 + in_define = True + if prev_stripped.startswith('define '): + decl_line = re.sub(r'^define\s+', 'declare ', prev_stripped) + decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) + decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) + paren_pos = decl_line.rfind(')') + if paren_pos >= 0: + decl_line = decl_line[:paren_pos + 1] + stub_lines.append(decl_line + '\n') + continue + + if stripped.startswith('@') and ' global ' in stripped and 'external global' not in stripped: + text_lines.append(line) + if ' internal ' not in stripped and ' private ' not in stripped: + name_match = re.match(r'(@\S+)', stripped) + if name_match: + var_name = name_match.group(1) + global_pos = stripped.find(' global ') + after_global = stripped[global_pos + 8:] + depth = 0 + type_end = len(after_global) + for ci, cc in enumerate(after_global): + if cc in ('{', '['): + depth += 1 + elif cc in ('}', ']'): + depth -= 1 + elif depth == 0 and cc == ' ': + type_end = ci + break + var_type = after_global[:type_end].strip() + brace_depth_gv = 0 + for cc in var_type: + if cc == '{': + brace_depth_gv += 1 + elif cc == '}': + brace_depth_gv -= 1 + if brace_depth_gv > 0: + in_global_def = True + global_var_name = var_name + global_type_parts = [var_type] + global_brace_depth = brace_depth_gv + elif var_type: + stub_lines.append(f'{var_name} = external global {var_type}\n') + continue + if stripped.startswith('@') and ' constant ' in stripped: + text_lines.append(line) + continue + + if stripped.startswith('declare'): + dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) + if dm: + fname = dm.group(1) + if fname in defined_names: + stub_lines.append(line) + continue + dot_pos = fname.find('.') + if dot_pos > 0: + fname_sha1 = fname[:dot_pos] + if module_sha1 and fname_sha1 != module_sha1 and len(fname_sha1) >= 16: + continue + if re.match(r'^[a-f0-9]{16}\.', fname): + continue + stub_lines.append(line) + continue + + stub_lines.append(line) + + return ''.join(stub_lines), ''.join(text_lines) + + def _save_deps(self, sha1: str, ModuleSha1Map: dict): + """保存依赖指纹到 .deps.json""" + deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") + deps = {} + for mod_name, dep_sha1 in ModuleSha1Map.items(): + deps[mod_name] = dep_sha1 + with open(deps_path, 'w', encoding='utf-8') as f: + json.dump(deps, f) + + def _LoadDeps(self, sha1: str) -> dict: + """加载依赖指纹""" + deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") + if os.path.isfile(deps_path): + try: + with open(deps_path, 'r', encoding='utf-8') as f: + return json.load(f) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"加载依赖指纹 JSON 失败: {_e}", "Exception") + return None + + def _check_deps_changed(self, sha1: str, current_ModuleSha1Map: dict) -> bool: + """检查依赖指纹是否变化""" + saved_deps = self._LoadDeps(sha1) + if saved_deps is None: + return True + for mod_name, dep_sha1 in current_ModuleSha1Map.items(): + if saved_deps.get(mod_name) != dep_sha1: + return True + for mod_name, dep_sha1 in saved_deps.items(): + if current_ModuleSha1Map.get(mod_name) != dep_sha1: + return True + return False + + def _recombine_ll(self, sha1: str, current_ModuleSha1Map: dict) -> bool: + """依赖变化时重新组合 .ll:更新 .stub.ll 中的 SHA1 前缀,拼接 .stub.ll + .text.ll""" + saved_deps = self._LoadDeps(sha1) + if saved_deps is None: + return False + + stub_path = os.path.join(self.output_dir, f"{sha1}.stub.ll") + text_path = os.path.join(self.output_dir, f"{sha1}.text.ll") + ll_path = os.path.join(self.output_dir, f"{sha1}.ll") + + if not os.path.isfile(stub_path) or not os.path.isfile(text_path): + return False + + with open(stub_path, 'r', encoding='utf-8') as f: + stub_content = f.read() + with open(text_path, 'r', encoding='utf-8') as f: + text_content = f.read() + + sha1_replacements = {} + for mod_name, old_sha1 in saved_deps.items(): + new_sha1 = current_ModuleSha1Map.get(mod_name) + if new_sha1 and old_sha1 != new_sha1: + sha1_replacements[old_sha1] = new_sha1 + + if sha1_replacements: + for old_sha1, new_sha1 in sha1_replacements.items(): + stub_content = stub_content.replace(old_sha1, new_sha1) + text_content = text_content.replace(old_sha1, new_sha1) + + combined = stub_content + if not combined.endswith('\n'): + combined += '\n' + combined += text_content + + with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(combined) + with open(stub_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(stub_content) + with open(text_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(text_content) + + self._save_deps(sha1, current_ModuleSha1Map) + + obj_path = os.path.join(self.output_dir, f"{sha1}.obj") + if os.path.isfile(obj_path): + os.remove(obj_path) + + return True + + def _translate_file(self, src_path: str, out_path: str, prebuilt_ModuleSha1Map: dict = None): + """翻译单个源文件,嵌入相关 .stub.ll 声明""" + with open(src_path, 'r', encoding='utf-8') as f: + code = f.read() + + sha1 = compute_sha1(code) + + if prebuilt_ModuleSha1Map is not None: + ModuleSha1Map = prebuilt_ModuleSha1Map + else: + ModuleSha1Map = self._build_current_ModuleSha1Map(sha1) + + trans = TransPyC.TransPyC(code=code, triple=self.triple, datalayout=self.datalayout) + trans.translator.CurrentFile = src_path + trans.SliceLevel = self.slice_level + trans.translator.SliceLevel = self.slice_level + trans.translator.SliceCount = 0 + trans.translator.SliceInfos = [] + trans.translator.LlvmGen = None + trans.translator._module_sha1 = sha1 + trans.translator._ModuleSha1Map = ModuleSha1Map + trans.translator._struct_sha1_map = self.struct_sha1_map + trans.translator._global_function_default_args = self.function_default_args + trans.translator._temp_dir = self.temp_dir + + if hasattr(self, '_shared_symbol_table') and self._shared_symbol_table is not None: + trans.translator.SymbolTable = self._shared_symbol_table + # 确保共享符号表的 translator 指向当前 translator,以便 import 别名解析正确 + if hasattr(self._shared_symbol_table, 'translator'): + self._shared_symbol_table.translator = trans.translator + trans.translator._source_module_sig_files = self._shared_source_module_sig_files + trans.translator._all_define_constants = self._shared_all_dc + trans.translator._export_extern_funcs = self._shared_export_extern_funcs + if hasattr(self, '_shared_generic_class_templates') and self._shared_generic_class_templates: + if not hasattr(trans.translator.ClassHandler, '_generic_class_templates'): + trans.translator.ClassHandler._generic_class_templates = {} + trans.translator.ClassHandler._generic_class_templates.update(self._shared_generic_class_templates) + else: + export_extern_funcs = set() + for sha1_key, sig_path in self.sig_files.items(): + if sha1_key == sha1: + continue + try: + with open(sig_path, 'r', encoding='utf-8') as f: + sig_content = f.read() + sig_tree = ast.parse(sig_content) + for node in ast.iter_child_nodes(sig_tree): + if isinstance(node, ast.FunctionDef): + if _check_annotation_for_export(node.returns): + export_extern_funcs.add(node.name) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"收集导出外部函数声明失败: {_e}", "Exception") + if export_extern_funcs: + trans.translator._export_extern_funcs = export_extern_funcs + + for includes_dir in self.include_dirs: + if os.path.isdir(includes_dir): + for pyi_file in os.listdir(includes_dir): + if pyi_file.endswith('.pyi'): + pyi_path = os.path.join(includes_dir, pyi_file) + module_name = os.path.splitext(pyi_file)[0] + trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) + for py_file in os.listdir(includes_dir): + if py_file.endswith('.py') and not py_file.startswith('_'): + module_name = os.path.splitext(py_file)[0] + sha1_key = self.include_py_map.get(module_name) + if sha1_key and sha1_key in self.sig_files: + sig_path = self.sig_files[sha1_key] + trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) + # 收集需要重导出的包,等所有模块符号加载完后再处理 + _pending_reexports = [] + for sha1_key, sig_path in self.sig_files.items(): + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if rel_path.startswith('includes/'): + mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + mod_name = mod_name[len('includes/'):] + trans.translator.SymbolTable.LoadModuleSymbols(sig_path, mod_name, lineno=0) + if mod_name.endswith('.__init__'): + package_name = mod_name[:-len('.__init__')] + _pending_reexports.append((sig_path, package_name)) + + # 所有 includes 模块符号已加载,现在处理包重导出 + for sig_path, package_name in _pending_reexports: + self._register_package_reexports(trans, sig_path, package_name) + + for sha1_key, sig_path in self.sig_files.items(): + if sha1_key == sha1: + continue + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if rel_path.startswith('includes/'): + continue + module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) + trans.translator._source_module_sig_files[module_name] = sig_path + short_name = module_name.split('.')[-1] if '.' in module_name else module_name + if short_name != module_name: + trans.translator._source_module_sig_files[short_name] = sig_path + + all_dc = {} + for sha1_key, stub_path in self.stub_files.items(): + if sha1_key == sha1: + continue + if os.path.exists(stub_path): + try: + with open(stub_path, 'r', encoding='utf-8') as f: + stub_content = f.read() + for line in stub_content.splitlines(): + line = line.strip() + if line.startswith('@') and '= global' in line and 'i32' in line and not line.startswith('@llvm'): + var_name = line.split('=')[0].strip().lstrip('@') + val_part = line.split('i32')[-1].strip().rstrip(']').lstrip('[').lstrip('i32') + try: + val = int(val_part) + all_dc[var_name] = val + except: + pass + except: + pass + for sha1_key, pyi_path in self.sig_files.items(): + if sha1_key == sha1: + continue + if os.path.exists(pyi_path): + try: + import ast as _ast + with open(pyi_path, 'r', encoding='utf-8') as f: + pyi_content = f.read() + tree = _ast.parse(pyi_content) + for node in _ast.iter_child_nodes(tree): + if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): + ann_str = _ast.dump(node.annotation) + if 'CDefine' in ann_str and node.value: + val = None + if isinstance(node.value, _ast.Constant): + val = node.value.value + elif isinstance(node.value, _ast.Call) and isinstance(node.value.func, _ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], _ast.Constant): + val = node.value.args[0].value + if val is not None: + all_dc[f"{node.target.id}"] = val + except: + pass + if all_dc: + trans.translator._all_define_constants = all_dc + + for sym_name, sym_info in self.inline_func_symbols.items(): + if sym_name not in trans.translator.SymbolTable: + trans.translator.SymbolTable[sym_name] = sym_info + else: + existing = trans.translator.SymbolTable[sym_name] + if not getattr(existing, 'InlineBody', None) and getattr(sym_info, 'InlineBody', None): + existing.IsInline = sym_info.IsInline + existing.InlineBody = sym_info.InlineBody + existing.InlineParams = sym_info.InlineParams + + try: + result = trans.Convert( + OutputFilename=out_path, + SourceFilename=src_path, + target='llvm' + ) + except Exception as e: + error_stack = getattr(trans.translator, '_ErrorStack', []) + if error_stack: + self._last_ErrorStack = error_stack + chain_lines = [] + for entry in reversed(error_stack): + if len(entry) >= 3: + exc_msg, line_info = entry[1], entry[2] + chain_lines.append(" %s\n %s" % (line_info, exc_msg)) + if chain_lines: + enriched = str(e) + "\n" + "\n".join(chain_lines) + raise type(e)(enriched) from e + node_info = "" + if hasattr(trans.translator, 'LlvmGen') and trans.translator.LlvmGen: + node_info = trans.translator.LlvmGen._get_node_info() + if node_info: + enriched = "%s\n %s" % (str(e), node_info.strip()) + raise type(e)(enriched) from e + raise + + if result and isinstance(result, str): + for func_name, func_def in trans.translator.FunctionDefCache.items(): + if hasattr(func_def, 'args') and hasattr(func_def.args, 'defaults') and func_def.args.defaults: + mangled = trans.translator.LlvmGen._mangle_func_name(func_name) if trans.translator.LlvmGen else func_name + defaults = [] + for d in func_def.args.defaults: + if isinstance(d, ast.Constant): + defaults.append(d.value) + else: + defaults.append(None) + self.function_default_args[mangled] = defaults + self.function_default_args[func_name] = defaults + for sym_name, sym_info in trans.translator.SymbolTable.items(): + if isinstance(sym_info, CTypeInfo) and getattr(sym_info, 'IsInline', False) and getattr(sym_info, 'InlineBody', None): + self.inline_func_symbols[sym_name] = sym_info + # stub声明现在通过_dso.ll编译时拼接依赖模块stub.ll提供 + # stub_decls = self._collect_stub_decls_for_module(sha1) + # if stub_decls: + # result = self._inject_stub_decls(result, stub_decls) + + out_dir = os.path.dirname(out_path) + if out_dir: + os.makedirs(out_dir, exist_ok=True) + with open(out_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(result) + + stub_content, text_content = self._split_ll(result) + base = os.path.splitext(out_path)[0] + with open(base + '.stub.ll', 'w', encoding='utf-8', newline='\n') as f: + f.write(stub_content) + with open(base + '.text.ll', 'w', encoding='utf-8', newline='\n') as f: + f.write(text_content) + self._save_deps(sha1, ModuleSha1Map) + + print(f" -> {os.path.basename(out_path)}") + else: + stub_path = self.stub_files.get(sha1) + if stub_path and os.path.exists(stub_path): + out_dir = os.path.dirname(out_path) + if out_dir: + os.makedirs(out_dir, exist_ok=True) + with open(stub_path, 'r', encoding='utf-8') as f: + stub_content = f.read() + with open(out_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(stub_content) + print(f" -> {os.path.basename(out_path)} (仅声明)") + + def _register_package_reexports(self, trans, init_pyi_path, package_name): + """解析 __init__.pyi 中的 from .xxx import yyy 或 from __xxx import yyy,在包级别注册导出符号""" + try: + with open(init_pyi_path, 'r', encoding='utf-8') as f: + content = f.read() + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.ImportFrom) and node.module: + sub_module = node.module.lstrip('.') + for alias in node.names: + symbol_name = alias.name + exported_name = alias.asname if alias.asname else symbol_name + source_keys = [ + f"{package_name}.{sub_module}.{symbol_name}", + f"{package_name}.__{sub_module}.{symbol_name}" if not sub_module.startswith('__') else None, + symbol_name, + ] + target_key = f"{package_name}.{exported_name}" + if target_key not in trans.translator.SymbolTable: + for source_key in source_keys: + if source_key and source_key in trans.translator.SymbolTable: + trans.translator.SymbolTable[target_key] = trans.translator.SymbolTable[source_key] + break + if exported_name not in trans.translator.SymbolTable: + for source_key in source_keys: + if source_key and source_key in trans.translator.SymbolTable: + trans.translator.SymbolTable[exported_name] = trans.translator.SymbolTable[source_key] + break + except Exception as e: + print(f" [警告] 解析包重导出失败 {init_pyi_path}: {e}") + + def _collect_stub_decls(self, self_sha1: str) -> str: + """收集 includes 目录中模块的 .stub.ll 声明内容,去重""" + seen_symbols = set() + decl_lines = [] + for sha1_key, stub_path in self.stub_files.items(): + if sha1_key == self_sha1: + continue + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if not rel_path.startswith('includes/'): + continue + if os.path.exists(stub_path): + with open(stub_path, 'r', encoding='utf-8') as f: + content = f.read() + for line in content.splitlines(): + stripped = line.strip() + if not stripped: + continue + if stripped.startswith(';'): + continue + if stripped.startswith('target '): + continue + if stripped.startswith('source_filename'): + continue + if stripped.startswith('@') and '=' in stripped: + name = stripped.split('=', 1)[0].strip() + if name in seen_symbols: + continue + seen_symbols.add(name) + elif stripped.startswith('%') and '= type' in stripped: + name = stripped.split('=', 1)[0].strip() + if name in seen_symbols: + continue + seen_symbols.add(name) + elif stripped.startswith('declare'): + parts = stripped.split('@', 1) + if len(parts) > 1: + name = '@' + parts[1].split('(', 1)[0].strip() + if name in seen_symbols: + continue + seen_symbols.add(name) + decl_lines.append(line) + if decl_lines: + result = '\n'.join(decl_lines) + self._stub_decls_cache[self_sha1] = result + return result + self._stub_decls_cache[self_sha1] = '' + return '' + + def _collect_stub_decls_for_module(self, self_sha1: str) -> str: + """收集特定模块需要的 .stub.ll 声明(包括结构体类型定义、函数声明和 typedef)""" + if self_sha1 in self._stub_decls_cache: + return self._stub_decls_cache[self_sha1] + import re + seen_symbols = set() + seen_func_symbols = set() + decl_lines = [] + + non_struct_types = {'UINT', 'INT', 'BYTE', 'BYTEPTR', 'WORD', 'DWORD', 'QWORD', + 'INT8', 'INT16', 'INT32', 'INT64', 'UINT8', 'UINT16', 'UINT32', 'UINT64', + 'INTPTR', 'UINTPTR', 'SIZE_T', 'SSIZE_T', 'PTRDIFF_T', + 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', + 'atomic_int', 'atomic_uint', 'atomic_long', 'atomic_ulong', + 'atomic_int8', 'atomic_uint8', 'atomic_int16', 'atomic_uint16', + 'atomic_int32', 'atomic_uint32', 'atomic_int64', 'atomic_uint64', + 'atomic_ptr', 'atomic_flag', 'typedef', + 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array'} + + struct_names = set() + struct_source_sha1 = {} + + def _extract_struct_name(type_def_str): + m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=\s*type', type_def_str) + if m: + raw = m.group(1) + if '.' in raw: + return raw.split('.', 1)[1], raw.split('.', 1)[0] + return raw, None + return None, None + + def _replace_struct_refs(type_str): + def replace_struct_name(name): + if name in struct_names: + name_sha1 = struct_source_sha1.get(name, '') + return f'%"{name_sha1}.{name}"' if name_sha1 else None + return None + def replace_struct_match(match): + name = match.group(1) + replaced = replace_struct_name(name) + return replaced if replaced else match.group(0) + def replace_sha1_struct_match(match): + name = match.group(2) + replaced = replace_struct_name(name) + return replaced if replaced else match.group(0) + result = re.sub(r'%struct\.(\w+)', replace_struct_match, type_str) + result = re.sub(r'%"?([a-f0-9]+)\.(\w+)"?', replace_sha1_struct_match, result) + return result + + for sha1_key, stub_path in self.stub_files.items(): + if os.path.exists(stub_path): + with open(stub_path, 'r', encoding='utf-8') as f: + content = f.read() + for line in content.splitlines(): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + clean_name, sha1_part = _extract_struct_name(stripped) + if clean_name and clean_name not in non_struct_types: + struct_names.add(clean_name) + if clean_name not in struct_source_sha1: + struct_source_sha1[clean_name] = sha1_part or sha1_key + + for sha1_key, stub_path in self.stub_files.items(): + if sha1_key == self_sha1: + continue + if os.path.exists(stub_path): + with open(stub_path, 'r', encoding='utf-8') as f: + content = f.read() + for line in content.splitlines(): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + clean_name, sha1_part = _extract_struct_name(stripped) + if not clean_name or clean_name in non_struct_types: + continue + if clean_name in seen_symbols: + continue + parts = stripped.split('= type', 1) + struct_type_body = parts[1].strip() if len(parts) > 1 else '' + if 'opaque' in struct_type_body: + seen_symbols.add(clean_name) + name_sha1 = struct_source_sha1.get(clean_name, sha1_key) + decl_lines.append(f'%"{name_sha1}.{clean_name}" = type opaque') + continue + if clean_name in struct_names: + struct_type_body = _replace_struct_refs(struct_type_body) + name_sha1 = struct_source_sha1.get(clean_name, sha1_key) + new_def = f'%"{name_sha1}.{clean_name}" = type {struct_type_body}' + seen_symbols.add(clean_name) + decl_lines.append(new_def) + if decl_lines: + return '\n'.join(decl_lines) + return '' + + def _inject_stub_decls(self, ll_content: str, stub_decls: str) -> str: + """将 stub 声明注入到 LLVM IR 模块头之后,替换 opaque 类型为具体定义""" + def normalize_type_name(name): + name = name.strip() + if name.startswith('%'): + return '%' + name[1:].strip().strip('"') + return name + + existing_symbols = {} # normalized_name -> (line_index, full_line) + for i, line in enumerate(ll_content.splitlines()): + stripped = line.strip() + if stripped.startswith('@') and '=' in stripped: + name = stripped.split('=', 1)[0].strip() + existing_symbols[name] = (i, line) + elif stripped.startswith('%') and '= type' in stripped: + name = normalize_type_name(stripped.split('=', 1)[0].strip()) + existing_symbols[name] = (i, line) + elif stripped.startswith('declare') or stripped.startswith('define'): + parts = stripped.split('@', 1) + if len(parts) > 1: + name = '@' + parts[1].split('(', 1)[0].strip() + existing_symbols[name] = (i, line) + + lines = ll_content.splitlines() + replacements = {} # line_index -> new_line + new_decls = [] # 新类型定义(不在现有输出中的) + + def normalize_type_name(name): + name = name.strip() + if name.startswith('%'): + return '%' + name[1:].strip().strip('"') + return name + + for line in stub_decls.splitlines(): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + name = normalize_type_name(stripped.split('=', 1)[0].strip()) + if name in existing_symbols: + idx, existing_line = existing_symbols[name] + existing_type_body = existing_line.strip().split('= type', 1)[1].strip() if '= type' in existing_line else '' + stub_type_body = stripped.split('= type', 1)[1].strip() if '= type' in stripped else '' + if 'opaque' in existing_line and 'opaque' not in stripped: + replacements[idx] = line + else: + new_decls.append(line) + + # 应用替换 + for idx, new_line in replacements.items(): + lines[idx] = new_line + + # 追加新类型定义到末尾(去重处理) + if new_decls: + # 过滤掉已经在 Translator 输出中存在的类型定义 + existing_types = set() + for line in lines: + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + type_name = normalize_type_name(stripped.split('=', 1)[0].strip()) + existing_types.add(type_name) + filtered_decls = [] + for line in new_decls: + stripped = line.strip() + if '= type' in stripped: + type_name = normalize_type_name(stripped.split('=', 1)[0].strip()) + if type_name not in existing_types: + filtered_decls.append(line) + existing_types.add(type_name) + if filtered_decls: + lines.append('') + lines.extend(filtered_decls) + + # 确保所有类型定义在全局变量之前,LLVM 要求在常量初始化器中使用类型之前必须先定义 + type_def_indices = [] + first_global_idx = None + for i, line in enumerate(lines): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + if first_global_idx is not None: + type_def_indices.append(i) + elif stripped.startswith('@') and ' global' in stripped: + if first_global_idx is None: + first_global_idx = i + + if type_def_indices and first_global_idx is not None: + type_defs = [lines[i] for i in reversed(type_def_indices)] + for i in reversed(type_def_indices): + del lines[i] + insert_pos = first_global_idx + if type_def_indices[0] < first_global_idx: + insert_pos = first_global_idx - len(type_def_indices) + for j, td in enumerate(type_defs): + lines.insert(insert_pos, td) + + result = '\n'.join(lines) + + return result + + def _compile_ll_files(self, active_sha1s: set): + """将 output_dir 中属于 active_sha1s 的 .ll 文件编译为 .obj(跳过已编译过的 include 文件)""" + stale_files = [] + for root, dirs, files in os.walk(self.output_dir): + for file in files: + fpath = os.path.join(root, file) + for ext in ('.ll', '.obj', '.stub.ll', '.text.ll', '.deps.json', '_dso.ll'): + if file.endswith(ext): + sha1 = file[:-(len(ext))] + if sha1 not in active_sha1s: + stale_files.append(fpath) + break + if stale_files: + for fpath in stale_files: + try: + os.remove(fpath) + except: + pass + print(f"[清理] 删除 {len(stale_files)} 个过时文件") + ll_files = [] + for root, dirs, files in os.walk(self.output_dir): + for file in files: + if file.endswith('.ll') and not file.endswith('.stub.ll') and not file.endswith('.text.ll'): + sha1 = file[:-3] + if sha1 in active_sha1s: + obj_path = os.path.join(root, file[:-3] + '.obj') + if not os.path.isfile(obj_path): + ll_files.append(os.path.join(root, file)) + + if not ll_files: + print("[编译] 无 .ll 文件需要重新编译") + else: + print(f"\n[编译] 找到 {len(ll_files)} 个 .ll 文件需要编译") + + has_inline = False + all_ll_files = [] + for root, dirs, files in os.walk(self.output_dir): + for file in files: + if file.endswith('.ll') and not file.endswith('.stub.ll') and not file.endswith('.text.ll'): + sha1 = file[:-3] + if sha1 in active_sha1s and sha1 not in self._include_sha1s: + all_ll_files.append(os.path.join(root, file)) + for ll_path in all_ll_files: + try: + with open(ll_path, 'r', encoding='utf-8') as f: + content = f.read() + if 'alwaysinline' in content: + has_inline = True + break + except: + pass + + if has_inline: + llvm_link = shutil.which('llvm-link') or shutil.which('llvm-link.exe') + opt_cmd = shutil.which('opt') or shutil.which('opt.exe') + if llvm_link and opt_cmd: + print(" [内联] 检测到 alwaysinline 函数,执行跨模块内联优化...") + for ll_path in all_ll_files: + try: + with open(ll_path, 'r', encoding='utf-8') as f: + content = f.read() + type_defs = [] + type_def_indices = set() + for i, line in enumerate(content.splitlines()): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + type_defs.append(line) + type_def_indices.add(i) + if type_def_indices: + lines = content.splitlines(True) + content_no_types = ''.join(line for i, line in enumerate(lines) if i not in type_def_indices) + header_end = 0 + for i, line in enumerate(content_no_types.splitlines()): + stripped = line.strip() + if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: + header_end = i + 1 + continue + break + lines2 = content_no_types.splitlines(True) + fixed = ''.join(lines2[:header_end]) + '\n'.join(type_defs) + '\n' + ''.join(lines2[header_end:]) + with open(ll_path, 'w', encoding='utf-8') as f: + f.write(fixed) + except: + pass + merged_ll = os.path.join(self.output_dir, '_merged.ll') + optimized_ll = os.path.join(self.output_dir, '_merged_opt.ll') + try: + link_cmd = [llvm_link] + all_ll_files + ['-o', merged_ll] + result = subprocess.run(link_cmd, capture_output=True, text=True) + if result.returncode != 0: + print(f" [警告] llvm-link 失败: {result.stderr.strip()},回退到单独编译") + has_inline = False + else: + opt_result_cmd = [opt_cmd, '-passes=always-inline', merged_ll, '-S', '-o', optimized_ll] + result = subprocess.run(opt_result_cmd, capture_output=True, text=True) + if result.returncode != 0: + print(f" [警告] opt 失败: {result.stderr.strip()},回退到单独编译") + has_inline = False + else: + print(" [内联] 跨模块内联优化完成") + with open(optimized_ll, 'r', encoding='utf-8') as f: + opt_content = f.read() + import re + opt_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', opt_content) + opt_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', opt_content) + opt_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', opt_content) + opt_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = linkonce_odr \2', opt_content) + with open(optimized_ll, 'w', encoding='utf-8') as f: + f.write(opt_content) + merged_obj = os.path.join(self.output_dir, '_merged.obj') + try: + cmd = [self.compile_cmd] + self.compile_flags + ['-o', merged_obj, optimized_ll] + result = subprocess.run(cmd, capture_output=True, text=True, + cwd=self.output_dir) + if result.returncode == 0: + print(f" [成功] 合并模块编译完成") + for ll_path in ll_files: + obj_path = ll_path[:-3] + '.obj' + sha1_obj = os.path.join(self.output_dir, os.path.basename(ll_path)[:-3] + '.obj') + if os.path.isfile(sha1_obj): + os.remove(sha1_obj) + return + else: + print(f" [警告] 合并模块编译失败: {result.stderr.strip()},回退到单独编译") + has_inline = False + except Exception as e: + print(f" [警告] 合并模块编译异常: {e},回退到单独编译") + has_inline = False + except FileNotFoundError: + print(f" [警告] 找不到 llvm-link 或 opt,回退到单独编译") + has_inline = False + else: + print(" [警告] 未找到 llvm-link/opt 工具,回退到单独编译(alwaysinline 可能不生效)") + + from concurrent.futures import ThreadPoolExecutor, as_completed + import re + + def _compile_one(ll_path): + rel = os.path.relpath(ll_path, self.output_dir) + obj_path = ll_path[:-3] + '.obj' + if os.path.isfile(obj_path): + return (rel, 'cached', '') + try: + with open(ll_path, 'r', encoding='utf-8') as f: + ll_content = f.read() + sha1 = os.path.basename(ll_path)[:-3] + deps = self._LoadDeps(sha1) + stub_prefix = '' + if deps: + existing_symbols = {} + opaque_line_indices = {} + existing_declares = set() + existing_declare_lines = {} + for i, line in enumerate(ll_content.splitlines()): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) + if m: + name = m.group(1) + if '= type opaque' in stripped: + existing_symbols[name] = 'opaque' + opaque_line_indices[name] = i + else: + existing_symbols[name] = 'full' + elif stripped.startswith('declare'): + dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) + if dm: + fname = dm.group(1) + existing_declares.add(fname) + existing_declare_lines[fname] = i + seen_stub_sha1 = set() + replaced_opaque_names = set() + replaced_declare_names = set() + all_stub_lines = [] + stub_type_map = {} + stub_declare_names = set() + stub_declare_lines = {} + existing_defines = set() + existing_global_defs = set() + stub_global_defs = set() + for line in ll_content.splitlines(): + stripped = line.strip() + if stripped.startswith('define'): + dm = re.match(r'define\s+[^@]*@"?([^"\s(]+)"?', stripped) + if dm: + existing_defines.add(dm.group(1)) + elif stripped.startswith('@') and (' global ' in stripped or ' constant ' in stripped): + gm = re.match(r'(@\S+)', stripped) + if gm: + existing_global_defs.add(gm.group(1)) + for dep_name, dep_sha1 in deps.items(): + if dep_sha1 in seen_stub_sha1: + continue + seen_stub_sha1.add(dep_sha1) + stub_path = os.path.join(self.output_dir, f"{dep_sha1}.stub.ll") + if not os.path.isfile(stub_path): + stub_path = os.path.join(self.temp_dir, f"{dep_sha1}.stub.ll") + if os.path.isfile(stub_path): + with open(stub_path, 'r', encoding='utf-8') as sf: + stub_content = sf.read() + for line in stub_content.splitlines(): + stripped = line.strip() + if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: + continue + if stripped.startswith('declare'): + dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) + if dm: + fname = dm.group(1) + if re.search(r'%("[^"]+"|[a-f0-9]+\.[A-Za-z_]\w*)\s+%', stripped): + continue + if fname in existing_defines: + continue + if fname in existing_declares or fname in stub_declare_names: + existing_decl_line = stub_declare_lines.get(fname) + if existing_decl_line is not None: + has_struct = '%' in stripped + existing_has_struct = '%' in existing_decl_line if existing_decl_line else False + if has_struct and not existing_has_struct: + for i, l in enumerate(all_stub_lines): + if l is not None and l.strip().startswith('declare'): + em = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', l.strip()) + if em and em.group(1) == fname: + all_stub_lines[i] = line + break + continue + elif fname in existing_declares: + has_struct = '%' in stripped + if has_struct: + replaced_declare_names.add(fname) + stub_declare_names.add(fname) + stub_declare_lines[fname] = line + all_stub_lines.append(line) + continue + continue + stub_declare_names.add(fname) + stub_declare_lines[fname] = line + all_stub_lines.append(line) + continue + if stripped.startswith('%') and '= type' in stripped: + m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) + if m: + name = m.group(1) + is_opaque = '= type opaque' in stripped + if name in existing_symbols: + if existing_symbols[name] == 'opaque' and not is_opaque: + replaced_opaque_names.add(name) + existing_symbols[name] = 'full' + idx = len(all_stub_lines) + all_stub_lines.append(line) + stub_type_map[name] = (is_opaque, idx) + continue + if name in stub_type_map: + prev_opaque, prev_idx = stub_type_map[name] + if prev_opaque and not is_opaque: + all_stub_lines[prev_idx] = None + idx = len(all_stub_lines) + all_stub_lines.append(line) + stub_type_map[name] = (is_opaque, idx) + continue + idx = len(all_stub_lines) + all_stub_lines.append(line) + stub_type_map[name] = (is_opaque, idx) + else: + all_stub_lines.append(line) + elif stripped.startswith('@') and (' global ' in stripped or ' constant ' in stripped): + gm = re.match(r'(@\S+)', stripped) + if gm and (gm.group(1) in existing_global_defs or gm.group(1) in stub_global_defs): + continue + if gm: + stub_global_defs.add(gm.group(1)) + all_stub_lines.append(line) + else: + all_stub_lines.append(line) + filtered = [l for l in all_stub_lines if l is not None] + if filtered: + stub_prefix = '\n'.join(filtered) + '\n' + lines_to_remove = set() + if replaced_opaque_names: + for name in replaced_opaque_names: + if name in opaque_line_indices: + lines_to_remove.add(opaque_line_indices[name]) + if replaced_declare_names: + for fname in replaced_declare_names: + if fname in existing_declare_lines: + lines_to_remove.add(existing_declare_lines[fname]) + if lines_to_remove: + ll_lines = ll_content.splitlines(True) + ll_content = ''.join(line for i, line in enumerate(ll_lines) if i not in lines_to_remove) + type_defs_in_ll = [] + type_def_line_indices = set() + for i, line in enumerate(ll_content.splitlines()): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + type_defs_in_ll.append(line) + type_def_line_indices.add(i) + if type_def_line_indices: + ll_lines = ll_content.splitlines(True) + ll_content = ''.join(line for i, line in enumerate(ll_lines) if i not in type_def_line_indices) + if type_defs_in_ll: + stub_prefix += '\n'.join(type_defs_in_ll) + '\n' + if stub_prefix: + header_end = 0 + for i, line in enumerate(ll_content.splitlines()): + stripped = line.strip() + if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: + header_end = i + 1 + continue + break + ll_lines = ll_content.splitlines(True) + ll_content = ''.join(ll_lines[:header_end]) + stub_prefix + ''.join(ll_lines[header_end:]) + ll_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content) + ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', ll_content) + ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) + ll_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content) + final_type_defs = [] + final_type_def_indices = set() + for i, line in enumerate(ll_content.splitlines()): + stripped = line.strip() + if stripped.startswith('%') and '= type' in stripped: + final_type_defs.append(line) + final_type_def_indices.add(i) + if final_type_def_indices: + final_lines = ll_content.splitlines(True) + ll_content_no_types = ''.join(line for i, line in enumerate(final_lines) if i not in final_type_def_indices) + header_end = 0 + for i, line in enumerate(ll_content_no_types.splitlines()): + stripped = line.strip() + if stripped.startswith(';') or stripped.startswith('target ') or stripped.startswith('source_filename') or not stripped: + header_end = i + 1 + continue + break + final_lines2 = ll_content_no_types.splitlines(True) + ll_content = ''.join(final_lines2[:header_end]) + '\n'.join(final_type_defs) + '\n' + ''.join(final_lines2[header_end:]) + dso_ll_path = ll_path[:-3] + '_dso.ll' + with open(dso_ll_path, 'w', encoding='utf-8') as f: + f.write(ll_content) + cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, dso_ll_path] + result = subprocess.run(cmd, capture_output=True, text=True, + cwd=os.path.dirname(ll_path) or '.') + if result.returncode == 0: + return (rel, 'ok', '') + else: + return (rel, 'error', result.stderr.strip()) + except FileNotFoundError: + return (rel, 'error', f'找不到编译器: {self.compile_cmd}') + except Exception as e: + return (rel, 'error', str(e)) + + need_compile = [] + for ll_path in ll_files: + obj_path = ll_path[:-3] + '.obj' + if not os.path.isfile(obj_path): + need_compile.append(ll_path) + + if need_compile: + n_workers = min(os.cpu_count() or 4, len(need_compile), 8) + print(f" 并行编译 {len(need_compile)} 个文件 (workers={n_workers})") + errors = [] + with ThreadPoolExecutor(max_workers=n_workers) as executor: + futures = {executor.submit(_compile_one, ll_path): ll_path for ll_path in need_compile} + for future in as_completed(futures): + rel, status, err = future.result() + if status == 'ok': + print(f" [成功] {rel}") + elif status == 'error': + print(f" [错误] {rel}: {err}") + errors.append((rel, err)) + elif status == 'cached': + pass + if errors: + print(f"\n[编译终止] {len(errors)} 个文件编译失败") + sys.exit(1) + + def _scan_include_libraries(self): + """扫描 includes 目录,检测被使用的模块对应的库文件和源文件""" + if not self.used_includes: + return + + for includes_dir in self.include_dirs: + if not os.path.isdir(includes_dir): + continue + + for module_name in self.used_includes: + module_dir = os.path.join(includes_dir, module_name) + if os.path.isdir(module_dir): + self._scan_dir_for_libs(module_dir, module_name) + for root, dirs, files in os.walk(module_dir): + dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] + for fname in files: + if fname.endswith('.py'): + py_path = os.path.join(root, fname) + if py_path not in self.extra_py_files: + self.extra_py_files.append(py_path) + print(f" [includes] 发现 Python 包文件: {os.path.relpath(py_path, includes_dir)}") + + for ext in self.INCLUDE_LIB_EXTENSIONS: + lib_path = os.path.join(includes_dir, module_name + ext) + if os.path.isfile(lib_path): + self.extra_link_files.append(lib_path) + print(f" [includes] 发现库文件: {os.path.relpath(lib_path, includes_dir)}") + + for ext in self.INCLUDE_SRC_EXTENSIONS: + src_path = os.path.join(includes_dir, module_name + ext) + if os.path.isfile(src_path): + self.extra_compile_files.append(src_path) + print(f" [includes] 发现源文件: {os.path.relpath(src_path, includes_dir)}") + + py_path = os.path.join(includes_dir, module_name + '.py') + if os.path.isfile(py_path): + self.extra_py_files.append(py_path) + print(f" [includes] 发现 Python 源文件: {os.path.relpath(py_path, includes_dir)}") + + discovered = set() + for ef in list(self.extra_py_files): + self._discover_transitive_deps(ef, includes_dir, discovered) + + if self.extra_link_files: + print(f"\n[includes] 需要链接的库文件: {len(self.extra_link_files)} 个") + if self.extra_compile_files: + print(f"[includes] 需要编译的源文件: {len(self.extra_compile_files)} 个") + + def _scan_dir_for_libs(self, directory: str, module_name: str): + """递归扫描目录中的库文件和源文件""" + for root, dirs, files in os.walk(directory): + for fname in files: + fpath = os.path.join(root, fname) + _, ext = os.path.splitext(fname) + ext = ext.lower() + if ext in self.INCLUDE_LIB_EXTENSIONS: + self.extra_link_files.append(fpath) + print(f" [includes] 发现库文件: {os.path.relpath(fpath, directory)}") + elif ext in self.INCLUDE_SRC_EXTENSIONS: + self.extra_compile_files.append(fpath) + print(f" [includes] 发现源文件: {os.path.relpath(fpath, directory)}") + + def _discover_transitive_deps(self, py_path: str, includes_dir: str, discovered: set): + """递归发现 Python 文件的间接依赖""" + if py_path in discovered: + return + discovered.add(py_path) + try: + with open(py_path, 'r', encoding='utf-8') as f: + content = f.read() + import ast as _ast + tree = _ast.parse(content) + for node in _ast.walk(tree): + if isinstance(node, _ast.Import): + for alias in node.names: + mod = alias.name.split('.')[0] + self._try_add_include_dep(mod, includes_dir, discovered) + elif isinstance(node, _ast.ImportFrom): + if node.module and node.level == 0: + mod = node.module.split('.')[0] + self._try_add_include_dep(mod, includes_dir, discovered) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"发现 include 传递依赖失败: {_e}", "Exception") + + def _try_add_include_dep(self, module_name: str, includes_dir: str, discovered: set): + """尝试将模块添加为 include 依赖""" + py_path = os.path.join(includes_dir, module_name + '.py') + if os.path.isfile(py_path) and py_path not in self.extra_py_files: + self.extra_py_files.append(py_path) + print(f" [includes] 发现间接依赖: {os.path.relpath(py_path, includes_dir)}") + self._discover_transitive_deps(py_path, includes_dir, discovered) + + def _is_decl_only_file(self, src_path: str) -> bool: + try: + with open(src_path, 'r', encoding='utf-8') as f: + content = f.read() + import ast as _ast + tree = _ast.parse(content) + for node in _ast.walk(tree): + if isinstance(node, _ast.ClassDef): + return False + if isinstance(node, _ast.FunctionDef): + body = node.body + if len(body) == 1: + stmt = body[0] + if isinstance(stmt, _ast.Expr) and isinstance(stmt.value, _ast.Constant) and stmt.value.value is ...: + continue + if isinstance(stmt, _ast.Pass): + continue + return False + return True + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"判断是否为声明文件失败: {_e}", "Exception") + return False + + def _sort_include_files_by_deps(self, file_list: list) -> list: + """按依赖关系对 include 文件进行拓扑排序,确保被依赖的文件先编译""" + import ast as _ast + + # 构建文件名到路径的映射 + name_to_path = {} + for fpath in file_list: + basename = os.path.splitext(os.path.basename(fpath))[0] + name_to_path[basename] = fpath + + # 也支持包内模块: vpsdk/window -> path + for fpath in file_list: + # 尝试从 includes 目录推断模块全名 + for includes_dir in self.include_dirs: + try: + rel = os.path.relpath(fpath, includes_dir) + mod_name = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + name_to_path[mod_name] = fpath + except ValueError: + pass + + # 分析每个文件的 import 依赖 + deps = {} # path -> set of paths it depends on + for fpath in file_list: + deps[fpath] = set() + try: + with open(fpath, 'r', encoding='utf-8') as f: + content = f.read() + tree = _ast.parse(content) + for node in _ast.iter_child_nodes(tree): + if isinstance(node, _ast.Import): + for alias in node.names: + mod = alias.name.split('.')[0] + if mod in name_to_path and name_to_path[mod] != fpath: + deps[fpath].add(name_to_path[mod]) + elif isinstance(node, _ast.ImportFrom): + if node.module and node.level == 0: + mod = node.module.split('.')[0] + if mod in name_to_path and name_to_path[mod] != fpath: + deps[fpath].add(name_to_path[mod]) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"分析 include 文件导入依赖失败: {_e}", "Exception") + + # 拓扑排序 (Kahn's algorithm) + in_degree = {fpath: len(deps[fpath]) for fpath in file_list} + # 反向邻接表:如果 A 依赖 B,则 B -> A + reverse_adj = {fpath: [] for fpath in file_list} + for fpath in file_list: + for dep in deps[fpath]: + if dep in reverse_adj: + reverse_adj[dep].append(fpath) + + result = [] + queue = [fpath for fpath in file_list if in_degree[fpath] == 0] + # 对队列排序以保持确定性 + queue.sort(key=lambda x: x) + + while queue: + current = queue.pop(0) + result.append(current) + for neighbor in reverse_adj[current]: + in_degree[neighbor] -= 1 + if in_degree[neighbor] == 0: + queue.append(neighbor) + queue.sort(key=lambda x: x) + + # 如果有循环依赖,把剩余文件也加入 + for fpath in file_list: + if fpath not in result: + result.append(fpath) + + return result + + def _compile_include_py_files(self, active_sha1s: set): + """通过 TransPyC 翻译器编译 includes 目录中发现的 .py 文件""" + if not self.extra_py_files: + return + + # 按依赖关系排序 include 文件,确保被依赖的文件先编译 + sorted_files = self._sort_include_files_by_deps(self.extra_py_files) + + print(f"\n[includes 编译] 找到 {len(sorted_files)} 个 Python 源文件") + + # 构建 include 文件的模块 SHA1 映射 + # 必须在编译前预构建完整的映射,否则后续文件引用前面文件时会用错误的 SHA1 + include_ModuleSha1Map = self._build_current_ModuleSha1Map(None) + # 预先为所有 include 文件计算 SHA1 并添加到映射中 + for src_path in sorted_files: + module_name = os.path.splitext(os.path.basename(src_path))[0] + with open(src_path, 'r', encoding='utf-8') as f: + py_content = f.read() + sha1 = compute_sha1(py_content) + self.include_py_map[module_name] = sha1 + active_sha1s.add(sha1) + self._include_sha1s.add(sha1) + + # 将 include 文件的模块名映射到其 SHA1 + for includes_dir in self.include_dirs: + try: + rel = os.path.relpath(src_path, includes_dir) + mod_full = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + include_ModuleSha1Map[mod_full] = sha1 + include_ModuleSha1Map[module_name] = sha1 + except ValueError: + pass + include_ModuleSha1Map[module_name] = sha1 + ll_path = os.path.join(self.output_dir, f"{sha1}.ll") + obj_path = os.path.join(self.output_dir, f"{sha1}.obj") + + if self._is_decl_only_file(src_path): + print(f" 跳过(声明文件): {module_name}.py") + self._collect_inline_symbols(src_path) + continue + + if os.path.isfile(obj_path): + print(f" 跳过(缓存): {module_name}.py -> {sha1}.obj") + self._collect_inline_symbols(src_path) + self.extra_link_files.append(obj_path) + continue + + print(f" 翻译: {os.path.basename(src_path)} -> {sha1}.ll") + + try: + self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map) + if os.path.isfile(ll_path): + print(f" 编译: {sha1}.ll -> {sha1}.obj") + with open(ll_path, 'r', encoding='utf-8') as f: + ll_content = f.read() + import re + ll_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content) + ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)', r'\1 dso_local ', ll_content) + ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) + ll_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content) + stub_decls = [] + for other_sha1, other_stub in self.stub_files.items(): + if other_sha1 == sha1: + continue + if os.path.exists(other_stub): + try: + with open(other_stub, 'r', encoding='utf-8') as sf: + for sline in sf: + sl = sline.strip() + if sl.startswith('%') and '= type' in sl and 'opaque' not in sl: + struct_name_match = re.match(r'%"?([\w.]+)"?\s*=', sl) + if struct_name_match: + stub_decls.append(sl) + except: + pass + if stub_decls: + for sdecl in stub_decls: + sname_match = re.match(r'%"?([\w.]+)"?\s*=\s*type', sdecl) + if sname_match: + sname = sname_match.group(1) + short = sname.split('.')[-1] if '.' in sname else sname + ll_content = re.sub( + r'%"?' + re.escape(sname) + r'"?\s*=\s*type\s*opaque', + sdecl, ll_content) + if short != sname: + ll_content = re.sub( + r'%"?' + re.escape(short) + r'"?\s*=\s*type\s*opaque', + sdecl, ll_content) + dso_ll_path = ll_path[:-3] + '_dso.ll' + with open(dso_ll_path, 'w', encoding='utf-8') as f: + f.write(ll_content) + cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, dso_ll_path] + result = subprocess.run( + cmd, + capture_output=True, + text=True, + cwd=self.output_dir + ) + if result.returncode == 0: + print(f" [成功]") + self.extra_link_files.append(obj_path) + + # 编译成功后,生成 .pyi 签名文件和 .stub.ll 文件 + # 并注册到符号表和签名映射中,以便后续 include 文件可以引用 + self._register_compiled_include(src_path, sha1, ll_content, include_ModuleSha1Map) + else: + print(f" [警告] 编译失败: {result.stderr.strip()}") + for ext in ['.ll', '_dso.ll']: + p = ll_path[:-3] + ext + if os.path.isfile(p): + os.remove(p) + else: + print(f" [错误] 翻译未生成 .ll 文件") + except Exception as e: + import traceback + for ext in ['.ll', '_dso.ll']: + p = ll_path[:-3] + ext + if os.path.isfile(p): + os.remove(p) + print(f" [错误] 翻译异常: {e}") + traceback.print_exc() + print(f"\n[编译终止] includes 文件翻译失败") + sys.exit(1) + + def _register_compiled_include(self, src_path, sha1, ll_content, include_ModuleSha1Map): + """编译 include 文件成功后,生成签名和 stub 文件并注册到符号表中""" + module_name = os.path.splitext(os.path.basename(src_path))[0] + + # 确定完整模块名(如 vpsdk.window) + mod_full = module_name + for includes_dir in self.include_dirs: + try: + rel = os.path.relpath(src_path, includes_dir) + mod_full = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + break + except ValueError: + pass + + # 1. 生成 .pyi 签名文件(如果还没有的话) + sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + if not os.path.isfile(sig_path): + try: + with open(src_path, 'r', encoding='utf-8') as f: + py_content = f.read() + sig_content = PythonToStubConverter.convert(py_content, mod_full) + os.makedirs(self.temp_dir, exist_ok=True) + with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(sig_content) + except Exception as e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"签名生成失败不阻塞编译: {e}", "Exception") + + # 注册到 sig_files 和 _source_module_sig_files + if os.path.isfile(sig_path): + self.sig_files[sha1] = sig_path + self.sha1_map[sha1] = f"includes/{mod_full.replace('.', os.sep)}.py" + if hasattr(self, '_shared_source_module_sig_files') and self._shared_source_module_sig_files is not None: + self._shared_source_module_sig_files[mod_full] = sig_path + self._shared_source_module_sig_files[module_name] = sig_path + + # 将签名信息加载到共享符号表中 + if hasattr(self, '_shared_symbol_table') and self._shared_symbol_table is not None: + try: + self._shared_symbol_table.LoadModuleSymbols(sig_path, mod_full, lineno=0) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"加载模块签名到共享符号表失败: {_e}", "Exception") + + # 2. 生成 .stub.ll 文件 + stub_path = os.path.join(self.output_dir, f"{sha1}.stub.ll") + if not os.path.isfile(stub_path) and ll_content: + try: + stub_content, _ = self._split_ll(ll_content) + with open(stub_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(stub_content) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"生成 .stub.ll 文件失败: {_e}", "Exception") + + # 注册到 stub_files + if os.path.isfile(stub_path): + self.stub_files[sha1] = stub_path + elif os.path.isfile(sig_path): + # 如果 stub 文件不存在,也尝试从 temp 目录查找 + temp_stub = os.path.join(self.temp_dir, f"{sha1}.stub.ll") + if os.path.isfile(temp_stub): + self.stub_files[sha1] = temp_stub + + def _precollect_inline_symbols(self): + """在主翻译循环之前,扫描includes目录中used_includes相关的模块收集内联函数AST""" + if not self.used_includes: + return + for includes_dir in self.include_dirs: + if not os.path.isdir(includes_dir): + continue + for module_name in self.used_includes: + module_dir = os.path.join(includes_dir, module_name) + if os.path.isdir(module_dir): + for root, dirs, files in os.walk(module_dir): + dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] + for fname in files: + if fname.endswith('.py'): + src_path = os.path.join(root, fname) + self._collect_inline_symbols(src_path) + py_path = os.path.join(includes_dir, module_name + '.py') + if os.path.isfile(py_path): + self._collect_inline_symbols(py_path) + for ef in self.extra_py_files: + self._collect_inline_symbols(ef) + + def _collect_inline_symbols(self, src_path: str): + """解析源文件,收集内联函数的AST信息到inline_func_symbols""" + try: + with open(src_path, 'r', encoding='utf-8') as f: + code = f.read() + tree = ast.parse(code) + module_name = os.path.splitext(os.path.basename(src_path))[0] + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.FunctionDef) and node.returns: + is_inline = False + if isinstance(node.returns, ast.BinOp) and isinstance(node.returns.op, ast.BitOr): + for part in [node.returns.left, node.returns.right]: + if isinstance(part, ast.Attribute) and part.attr == 'CInline': + is_inline = True + break + if isinstance(part, ast.Name) and part.id == 'CInline': + is_inline = True + break + elif isinstance(node.returns, ast.Attribute) and node.returns.attr == 'CInline': + is_inline = True + elif isinstance(node.returns, ast.Name) and node.returns.id == 'CInline': + is_inline = True + if is_inline: + func_name = node.name + sym_key = f"{module_name}.{func_name}" + info = CTypeInfo() + info.Name = func_name + info.IsFunction = True + info.IsInline = True + info.InlineBody = node.body + info.InlineParams = [arg.arg for arg in node.args.args] + info.Storage = t.CInline() + self.inline_func_symbols[func_name] = info + self.inline_func_symbols[sym_key] = info + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"预收集内联函数符号失败: {_e}", "Exception") + + def _build_shared_symbol_data(self): + """一次性构建所有文件共享的符号表数据,避免每个文件重复加载""" + import copy + import time + t0 = time.time() + + print("[缓存] 构建共享符号表数据...") + + base_trans = TransPyC.TransPyC(code="pass", triple=self.triple, datalayout=self.datalayout) + base_trans.translator.LlvmGen = None + base_trans.translator._ModuleSha1Map = {} + base_trans.translator._global_function_default_args = self.function_default_args + + for includes_dir in self.include_dirs: + if os.path.isdir(includes_dir): + for pyi_file in os.listdir(includes_dir): + if pyi_file.endswith('.pyi'): + pyi_path = os.path.join(includes_dir, pyi_file) + module_name = os.path.splitext(pyi_file)[0] + base_trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) + for py_file in os.listdir(includes_dir): + if py_file.endswith('.py') and not py_file.startswith('_'): + module_name = os.path.splitext(py_file)[0] + sha1_key = self.include_py_map.get(module_name) + if sha1_key and sha1_key in self.sig_files: + sig_path = self.sig_files[sha1_key] + base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) + # 收集需要重导出的包,等所有模块符号加载完后再处理 + _pending_reexports = [] + for sha1_key, sig_path in self.sig_files.items(): + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if rel_path.startswith('includes/'): + mod_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + mod_name = mod_name[len('includes/'):] + base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, mod_name, lineno=0) + if mod_name.endswith('.__init__'): + package_name = mod_name[:-len('.__init__')] + _pending_reexports.append((sig_path, package_name)) + + # 所有 includes 模块符号已加载,现在处理包重导出 + for sig_path, package_name in _pending_reexports: + self._register_package_reexports(base_trans, sig_path, package_name) + + for sha1_key, sig_path in self.sig_files.items(): + rel_path = self.sha1_map.get(sha1_key, sha1_key) + if rel_path.startswith('includes/'): + continue + module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + base_trans.translator.SymbolTable.LoadModuleSymbols(sig_path, module_name, lineno=0) + base_trans.translator._source_module_sig_files[module_name] = sig_path + short_name = module_name.split('.')[-1] if '.' in module_name else module_name + if short_name != module_name: + base_trans.translator._source_module_sig_files[short_name] = sig_path + + all_dc = {} + for sha1_key, stub_path in self.stub_files.items(): + if os.path.exists(stub_path): + try: + with open(stub_path, 'r', encoding='utf-8') as f: + stub_content = f.read() + for line in stub_content.splitlines(): + line = line.strip() + if line.startswith('@') and '= global' in line and 'i32' in line and not line.startswith('@llvm'): + var_name = line.split('=')[0].strip().lstrip('@') + val_part = line.split('i32')[-1].strip().rstrip(']').lstrip('[').lstrip('i32') + try: + val = int(val_part) + all_dc[var_name] = val + except: + pass + except: + pass + + for sha1_key, pyi_path in self.sig_files.items(): + if os.path.exists(pyi_path): + try: + with open(pyi_path, 'r', encoding='utf-8') as f: + pyi_content = f.read() + tree = ast.parse(pyi_content) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + ann_str = ast.dump(node.annotation) + if 'CDefine' in ann_str and node.value: + val = None + if isinstance(node.value, ast.Constant): + val = node.value.value + elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], ast.Constant): + val = node.value.args[0].value + if val is not None: + all_dc[f"{node.target.id}"] = val + except: + pass + + export_extern_funcs = set() + for sha1_key, sig_path in self.sig_files.items(): + try: + with open(sig_path, 'r', encoding='utf-8') as f: + sig_content = f.read() + sig_tree = ast.parse(sig_content) + for node in ast.iter_child_nodes(sig_tree): + if isinstance(node, ast.FunctionDef): + if _check_annotation_for_export(node.returns): + export_extern_funcs.add(node.name) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"收集共享导出外部函数失败: {_e}", "Exception") + + for sym_name, sym_info in self.inline_func_symbols.items(): + if sym_name not in base_trans.translator.SymbolTable: + base_trans.translator.SymbolTable[sym_name] = sym_info + else: + existing = base_trans.translator.SymbolTable[sym_name] + if not getattr(existing, 'InlineBody', None) and getattr(sym_info, 'InlineBody', None): + existing.IsInline = sym_info.IsInline + existing.InlineBody = sym_info.InlineBody + existing.InlineParams = sym_info.InlineParams + + self._shared_symbol_table = base_trans.translator.SymbolTable + self._shared_source_module_sig_files = dict(base_trans.translator._source_module_sig_files) + self._shared_all_dc = all_dc + self._shared_export_extern_funcs = export_extern_funcs + + generic_class_templates = {} + for includes_dir in self.include_dirs: + if os.path.isdir(includes_dir): + abs_includes = os.path.join(self.src_root, includes_dir) if not os.path.isabs(includes_dir) else includes_dir + if not os.path.isdir(abs_includes): + abs_includes = includes_dir + for py_file in os.listdir(abs_includes): + if py_file.endswith('.py') and not py_file.startswith('_'): + py_path = os.path.join(abs_includes, py_file) + try: + with open(py_path, 'r', encoding='utf-8') as f: + py_code = f.read() + py_tree = ast.parse(py_code) + for node in py_tree.body: + if isinstance(node, ast.ClassDef) and hasattr(node, 'type_params') and node.type_params: + type_params = [tp.name for tp in node.type_params] + generic_class_templates[node.name] = { + 'node': node, + 'type_params': type_params, + } + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"收集泛型类模板失败: {_e}", "Exception") + self._shared_generic_class_templates = generic_class_templates + + t1 = time.time() + print(f"[缓存] 共享符号表构建完成 ({t1-t0:.2f}s, {len(self._shared_symbol_table)} 符号, {len(generic_class_templates)} 泛型模板)") + + def _compile_include_sources(self): + """扫描项目目录中的汇编存根,编译 includes 目录中发现的 C/C++ 源文件""" + extra_sources = list(self.extra_compile_files) + scan_dirs = [] + if self.src_root and os.path.isdir(self.src_root): + scan_dirs.append(self.src_root) + project_dir = os.path.dirname(self.output_dir) + if project_dir and os.path.isdir(project_dir) and project_dir not in scan_dirs: + scan_dirs.append(project_dir) + for scan_dir in scan_dirs: + for root, dirs, files in os.walk(scan_dir): + dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] + for fname in files: + if fname.endswith(('.S', '.s', '.c', '.cpp')): + if fname.startswith('test_'): + continue + fpath = os.path.join(root, fname) + if fpath not in extra_sources: + extra_sources.append(fpath) + if not extra_sources: + return + + cc_map = { + '.c': 'gcc', + '.cpp': 'g++', '.cc': 'g++', '.cxx': 'g++', + '.m': 'clang', '.mm': 'clang++', + '.s': 'gcc', '.S': 'gcc', + } + + print(f"\n[includes 编译] 找到 {len(extra_sources)} 个源文件") + + for src_path in extra_sources: + _, ext = os.path.splitext(src_path) + ext = ext.lower() + obj_path = os.path.join(self.output_dir, os.path.splitext(os.path.basename(src_path))[0] + '.obj') + if ext in ('.s', '.S') and any('oformat' in f for f in self.linker_flags): + cc = 'clang' + compile_src = src_path + extra_flags = ['-c', '-target', 'x86_64-none-elf', '-o', obj_path, compile_src] + else: + cc = cc_map.get(ext, 'gcc') + extra_flags = ['-c', '-o', obj_path, src_path] + + print(f" 编译: {os.path.basename(src_path)} -> {os.path.basename(obj_path)}") + + try: + cmd = [cc] + extra_flags + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode == 0: + print(f" [成功]") + self.extra_link_files.append(obj_path) + else: + print(f" [错误] 编译失败: {result.stderr.strip()}") + print(f"\n[编译终止] C/C++ 源文件编译失败,立即终止编译。") + sys.exit(1) + except FileNotFoundError: + print(f" [错误] 找不到编译器: {cc}") + print(f"\n[编译终止] 找不到编译器,立即终止编译。") + sys.exit(1) + except Exception as e: + print(f" [错误] {e}") + print(f"\n[编译终止] 编译异常,立即终止编译。") + sys.exit(1) + + def _strip_debug_sections(self, exe_path: str): + """剥离 .exe 中的调试段(跳过裸机二进制)""" + if not os.path.exists(exe_path): + return + ext = os.path.splitext(exe_path)[1].lower() + if ext not in ('.exe', '.dll', '.obj', '.o', '.elf'): + print(f" [剥离] 跳过({ext} 格式无需剥离)") + return + import shutil + for tool in ['llvm-strip', 'strip']: + strip_cmd = shutil.which(tool) + if strip_cmd: + try: + result = subprocess.run( + [strip_cmd, '--strip-debug', exe_path], + capture_output=True, text=True + ) + if result.returncode == 0: + print(f" [剥离] 调试段已移除 ({tool})") + else: + print(f" [剥离] 警告: {result.stderr.strip()}") + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"剥离可执行文件调试段失败: {_e}", "Exception") + break + + def _generate_startup_obj(self): + """当 project.json 中配置了 startup 时,生成符号别名 shim。 + + startup 配置格式: + true -> 等价于 {"__main": "main"} + {"__main": "main", "_start": "main"} -> 为每个别名生成调用目标函数的包装 + + 生成的 .ll 会被编译为 _startup.obj 并加入链接列表。 + """ + if not self.startup: + return None + + # 归一化配置 + if self.startup is True: + aliases = {"__main": "main"} + elif isinstance(self.startup, dict): + aliases = self.startup + else: + return None + + # 构建 LLVM IR + decls = [] + defs = [] + for alias_name, target_name in aliases.items(): + # 声明目标函数 + decls.append(f"declare i32 @{target_name}()") + # 定义别名函数:调用目标函数并返回其返回值 + defs.append( + f"define dso_local i32 @{alias_name}() {{\n" + f"entry:\n" + f" %r = call i32 @{target_name}()\n" + f" ret i32 %r\n" + f"}}\n" + ) + + ll_content = "; startup shim (auto-generated)\n" + "\n".join(decls) + "\n\n" + "\n".join(defs) + "\n" + + ll_path = os.path.join(self.output_dir, '_startup.ll') + obj_path = os.path.join(self.output_dir, '_startup.obj') + + with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(ll_content) + + # 编译为 .obj + cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, ll_path] + result = subprocess.run(cmd, capture_output=True, text=True, cwd=self.output_dir or '.') + if result.returncode != 0: + print(f" [startup] 编译失败: {result.stderr.strip()}") + return None + + print(f" [startup] 生成符号别名: {aliases}") + return obj_path + + def _link_obj_files(self, active_sha1s: set): + """将 active_sha1s 对应的 .obj 文件和 includes 库文件链接为可执行文件""" + obj_files = [] + merged_obj = os.path.join(self.output_dir, '_merged.obj') + if os.path.isfile(merged_obj): + obj_files.append(merged_obj) + else: + for root, dirs, files in os.walk(self.output_dir): + for file in files: + if file.endswith('.obj'): + sha1 = file[:-4] + if sha1 in active_sha1s and sha1 not in self._include_sha1s: + obj_files.append(os.path.join(root, file)) + + if not obj_files and not self.extra_link_files: + print("[链接] 无文件可链接") + return + + # 生成 startup 符号别名 shim + startup_obj = self._generate_startup_obj() + if startup_obj: + obj_files.append(startup_obj) + + print(f"\n[链接] 找到 {len(obj_files)} 个 .obj 文件") + + all_link_files = obj_files + self.extra_link_files + seen = set() + all_link_files = [f for f in all_link_files if not (f in seen or seen.add(f))] + if self.extra_link_files: + print(f"[链接] 额外库文件: {len(self.extra_link_files)} 个") + for lib in self.extra_link_files: + print(f" - {os.path.basename(lib)}") + + if not self.linker_cmd: + print("[链接] 未配置链接器") + return + + exe_path = os.path.join(self.output_dir, self.linker_output) if self.linker_output else os.path.join(self.output_dir, 'a.exe') + is_binary = self.linker_output and self.linker_output.endswith('.bin') + + # 检查是否直接输出二进制(使用 --oformat binary / -oformat binary 标志) + is_direct_binary = is_binary and any('oformat' in f for f in self.linker_flags) + + if is_binary and not is_direct_binary: + link_output = exe_path[:-4] + '_pe.exe' + else: + link_output = exe_path + + # 自动复制或生成 linker.ld 到输出目录 + linker_ld_src = os.path.join(os.path.dirname(self.output_dir), 'linker.ld') + linker_ld_dst = os.path.join(self.output_dir, 'linker.ld') + if os.path.isfile(linker_ld_src) and not os.path.isfile(linker_ld_dst): + import shutil + shutil.copy2(linker_ld_src, linker_ld_dst) + print(f" [链接] 使用链接脚本: linker.ld") + elif not os.path.isfile(linker_ld_dst) and any('-T' in f or '-T' in f.replace(',', ' ') for f in self.linker_flags): + default_ld = """ENTRY(_start) + +SECTIONS { + . = 0x100000; + + .text : { + *(.text.startup) + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + .data : { + *(.data) + *(.data.*) + } + + .bss : { + *(.bss) + *(.bss.*) + } + + /DISCARD/ : { + *(.comment) + *(.note) + *(.eh_frame) + *(.eh_frame_hdr) + *(.reloc) + *(.rela) + *(.debug*) + } +} +""" + with open(linker_ld_dst, 'w', encoding='utf-8', newline='\n') as f: + f.write(default_ld) + print(f" [链接] 自动创建默认链接脚本: linker.ld") + + try: + # 将 linker_flags 拆分为非库标志和库标志(-l/-L),库标志放在目标文件之后 + # 这样 Unix 风格链接器才能正确解析库中的符号 + # -Wl, 选项是链接器全局选项,放在目标文件之前 + non_lib_flags = [] + lib_flags = [] + i = 0 + while i < len(self.linker_flags): + flag = self.linker_flags[i] + if flag in ('-l', '-L') and i + 1 < len(self.linker_flags): + # -l xxx / -L xxx 分开的形式 + lib_flags.extend([flag, self.linker_flags[i + 1]]) + i += 2 + elif flag.startswith('-l') or flag.startswith('-L'): + # -lxxx / -Lxxx 合并的形式 + lib_flags.append(flag) + i += 1 + else: + # 其他所有标志(包括 -Wl, 选项)放在目标文件之前 + non_lib_flags.append(flag) + i += 1 + cmd = [self.linker_cmd] + non_lib_flags + ['-o', link_output] + all_link_files + lib_flags + print(f" 执行: {' '.join(cmd)}") + result = subprocess.run( + cmd, + capture_output=True, + text=True, + cwd=self.output_dir or '.' + ) + if result.returncode == 0: + if is_binary and not is_direct_binary: + import shutil + objcopy = shutil.which('llvm-objcopy') or shutil.which('objcopy') + if objcopy: + conv = subprocess.run( + [objcopy, '-O', 'binary', link_output, exe_path], + capture_output=True, text=True + ) + if conv.returncode == 0: + os.remove(link_output) + print(f" [成功] 生成裸机二进制: {exe_path}") + file_size = os.path.getsize(exe_path) + print(f" [大小] {file_size} 字节") + else: + print(f" [错误] 二进制转换失败: {conv.stderr.strip()}") + sys.exit(1) + else: + print(" [错误] 找不到 llvm-objcopy,无法生成裸机二进制") + sys.exit(1) + else: + print(f" [成功] 生成: {exe_path}") + file_size = os.path.getsize(exe_path) + print(f" [大小] {file_size} 字节") + if not is_binary: + self._strip_debug_sections(exe_path) + else: + print(f" [错误] 链接失败: {result.stderr.strip()}") + print(f"\n[编译终止] 链接失败,立即终止编译。") + sys.exit(1) + except FileNotFoundError: + print(f" [错误] 找不到链接器: {self.linker_cmd}") + print(f"\n[编译终止] 找不到链接器,立即终止编译。") + sys.exit(1) + except Exception as e: + print(f" [错误] {e}") + print(f"\n[编译终止] 链接异常,立即终止编译。") + sys.exit(1) diff --git a/lib/Projectrans/Utils.py b/lib/Projectrans/Utils.py new file mode 100644 index 0000000..834fec7 --- /dev/null +++ b/lib/Projectrans/Utils.py @@ -0,0 +1,170 @@ +import hashlib +import os +import ast + + +def compute_sha1(content: str) -> str: + return hashlib.sha1(content.encode('utf-8')).hexdigest()[:16] + + +def _check_annotation_for_export(annotation) -> bool: + """递归检查类型注解中是否包含 CExport""" + if annotation is None: + return False + if isinstance(annotation, ast.Attribute): + if hasattr(annotation, 'attr') and annotation.attr == 'CExport': + return True + elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + return _check_annotation_for_export(annotation.left) or _check_annotation_for_export(annotation.right) + elif isinstance(annotation, ast.Name): + return annotation.id == 'CExport' + return False + + +def sha1_file(filepath: str) -> str: + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + return compute_sha1(content) + + +def get_file_dependencies(filepath: str, src_root: str) -> set: + """解析 Python 文件的导入依赖""" + dependencies = set() + try: + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.Import): + for alias in node.names: + module = alias.name + dependencies.add(module) + elif isinstance(node, ast.ImportFrom): + if node.module: + module = node.module + if node.level > 0: + # from .module import name → 依赖 pkg.module(模块本身) + pkg_dir = os.path.dirname(filepath) + pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') + if pkg_rel == '.': + pkg_rel = '' + if pkg_rel: + dep_module = f'{pkg_rel}.{module}' + else: + dep_module = module + dependencies.add(dep_module) + else: + if not module.startswith('_'): + dependencies.add(module) + elif node.level > 0 and node.names: + # from . import name → 依赖 pkg.name(子模块) + for alias in node.names: + pkg_dir = os.path.dirname(filepath) + pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') + if pkg_rel == '.': + pkg_rel = '' + dep_module = f'{pkg_rel}.{alias.name}' if pkg_rel else alias.name + dependencies.add(dep_module) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析文件导入依赖失败: {_e}", "Exception") + return dependencies + + +def find_reachable_files_from_entries(src_root: str, entry_files: list) -> set: + """从入口文件出发,找出所有可达的 .py 文件(通过导入关系)""" + all_files = {} # module_name -> filepath + for root, dirs, files in os.walk(src_root): + dirs[:] = [d for d in dirs if d not in ('__pycache__',)] + for file in files: + if file.endswith('.py'): + filepath = os.path.join(root, file) + rel = os.path.relpath(filepath, src_root) + module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + if filepath.endswith('__init__.py'): + all_files[module] = filepath + parent_module = module.rsplit('.', 1)[0] if '.' in module else module + if parent_module not in all_files or not all_files[parent_module].endswith('__init__.py'): + all_files[parent_module] = filepath + elif module not in all_files: + all_files[module] = filepath + top_module = module.split('.')[0] + if top_module not in all_files: + all_files[top_module] = filepath + + reachable = set() + queue = list(entry_files) + + while queue: + current = queue.pop(0) + if current in reachable: + continue + reachable.add(current) + deps = get_file_dependencies(current, src_root) + for dep in deps: + if dep in all_files and all_files[dep] not in reachable: + queue.append(all_files[dep]) + else: + for key, val in all_files.items(): + if key.endswith('.' + dep) or key == dep: + if val not in reachable: + queue.append(val) + break + + return reachable + + +def topological_sort_files(py_files: list, src_root: str) -> list: + """对 Python 文件进行拓扑排序,确保依赖模块先被处理""" + # 构建模块名到文件路径的映射 + module_to_file = {} + for filepath in py_files: + rel = os.path.relpath(filepath, src_root) + module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + module_to_file[module] = filepath + # 也添加顶层模块名 + top_module = module.split('.')[0] + if top_module not in module_to_file: + module_to_file[top_module] = filepath + + # 构建依赖图 + graph = {f: set() for f in py_files} + for filepath in py_files: + deps = get_file_dependencies(filepath, src_root) + for dep in deps: + if dep in module_to_file: + dep_file = module_to_file[dep] + if dep_file != filepath: # 避免自依赖 + graph[filepath].add(dep_file) + + # 拓扑排序 (Kahn's algorithm) + in_degree = {f: 0 for f in py_files} + for f, deps in graph.items(): + for dep in deps: + if dep in in_degree: + in_degree[f] += 1 + + queue = [f for f, degree in in_degree.items() if degree == 0] + sorted_files = [] + + while queue: + # 按字母顺序处理同级别的文件,确保确定性 + queue.sort() + current = queue.pop(0) + sorted_files.append(current) + + for f, deps in graph.items(): + if current in deps: + in_degree[f] -= 1 + if in_degree[f] == 0: + queue.append(f) + + # 如果有环,添加剩余文件 + if len(sorted_files) < len(py_files): + remaining = [f for f in py_files if f not in sorted_files] + sorted_files.extend(remaining) + + return sorted_files diff --git a/lib/Projectrans/__init__.py b/lib/Projectrans/__init__.py new file mode 100644 index 0000000..2506ee1 --- /dev/null +++ b/lib/Projectrans/__init__.py @@ -0,0 +1,37 @@ +"""Projectrans 包 - 工程级 TransPyC 翻译器""" +import os +import sys + +# 确保项目根目录在 sys.path 中,以便 import TransPyC 和 from StubGen import ... 正常工作 +_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +if _PROJECT_ROOT not in sys.path: + sys.path.insert(0, _PROJECT_ROOT) + +from lib.core.VLogger import Logger, LogLevel, set_logger + +# 创建全局日志实例 +logger = Logger( + name="TransPyC", + log_file="build.log", + level=LogLevel.INFO, + use_colors=True +) +set_logger(logger) + +from lib.Projectrans.Utils import ( + compute_sha1, _check_annotation_for_export, sha1_file, + get_file_dependencies, find_reachable_files_from_entries, + topological_sort_files +) +from lib.Projectrans.Phase1Generator import Phase1Generator +from lib.Projectrans.DeclarationGenerator import DeclarationGenerator +from lib.Projectrans.Phase2Translator import Phase2Translator, _parallel_translate_worker +from lib.Projectrans.Config import save_sha1_map, Load_sha1_map, Load_project_config, resolve_paths, main + +__all__ = [ + 'compute_sha1', '_check_annotation_for_export', 'sha1_file', + 'get_file_dependencies', 'find_reachable_files_from_entries', + 'topological_sort_files', 'Phase1Generator', 'DeclarationGenerator', + 'Phase2Translator', '_parallel_translate_worker', + 'save_sha1_map', 'Load_sha1_map', 'Load_project_config', 'resolve_paths', 'main' +] diff --git a/lib/Shell/Config.py b/lib/Shell/Config.py new file mode 100644 index 0000000..77bcaae --- /dev/null +++ b/lib/Shell/Config.py @@ -0,0 +1,5 @@ +class Config: + """配置类""" + def __init__(self): + self.debug = False + self.mode = 'relaxed' # 'relaxed' 或 'strict' diff --git a/lib/Shell/Serializer.py b/lib/Shell/Serializer.py new file mode 100644 index 0000000..8df3965 --- /dev/null +++ b/lib/Shell/Serializer.py @@ -0,0 +1,58 @@ +import json +import struct + + +def SerializeSymbolTable(SymbolTable: dict) -> bytes: + """将符号表序列化为二进制格式 + + 格式: + - 4字节: JSON数据长度(小端序) + - N字节: JSON数据(UTF-8编码) + + Args: + SymbolTable: 符号表字典 + + Returns: + 二进制字节数据 + """ + JsonData = json.dumps(SymbolTable, ensure_ascii=False).encode('utf-8') + length = len(JsonData) + # 使用4字节小端序整数表示长度 + header = struct.pack(' dict: + """从二进制数据反序列化符号表 + + Args: + data: 二进制字节数据 + + Returns: + 符号表字典 + """ + if len(data) < 4: + raise ValueError("Invalid symbin file: data too short") + # 解析4字节长度头(小端序) + length = struct.unpack(' -o [-debug ] + if I + 1 < len(sys.argv): + InputFile = sys.argv[I + 1] + I += 2 + + # 解析可选参数 + OutputFile = None + DebugFile = None + while I < len(sys.argv) and sys.argv[I].startswith('-'): + if sys.argv[I] == '-o': + if I + 1 < len(sys.argv): + OutputFile = sys.argv[I + 1] + I += 2 + else: + print(f'Error: -o requires an argument') + sys.exit(1) + elif sys.argv[I] == '-debug': + if I + 1 < len(sys.argv): + DebugFile = sys.argv[I + 1] + I += 2 + else: + print(f'Error: -debug requires an argument') + sys.exit(1) + else: + break + + # 如果没有指定输出文件,使用默认名称 + if not OutputFile: + OutputFile = InputFile.replace('.py', '.symbin').replace('.c', '.symbin') + + # 执行预处理 + self.Args['PreSym'] = { + 'input': InputFile, + 'output': OutputFile, + 'debug': DebugFile + } + else: + print(f'Error: -presym requires an argument') + sys.exit(1) + elif sys.argv[I] == '-e' or sys.argv[I] == '--encoding': + if I + 1 < len(sys.argv): + self.Args['Encoding'] = sys.argv[I + 1] + I += 2 + else: + print(f'Error: -e/--encoding requires an argument') + sys.exit(1) + elif sys.argv[I] == '--triple': + if I + 1 < len(sys.argv): + self.triple = sys.argv[I + 1] + I += 2 + else: + print(f'Error: --triple requires an argument') + sys.exit(1) + elif sys.argv[I] == '--datalayout': + if I + 1 < len(sys.argv): + self.datalayout = sys.argv[I + 1] + I += 2 + else: + print(f'Error: --datalayout requires an argument') + sys.exit(1) + else: + print(f'Error: Unknown argument {sys.argv[I]}') + sys.exit(1) + + # 检查是否有预处理符号文件的请求,如果有则跳过输入输出检查 + if 'PreSym' not in self.Args and ('Input' not in self.Args or 'Output' not in self.Args): + print(ERROR_MESSAGES['MISSING_ARGS']) + print(HELP_MESSAGE) + sys.exit(1) + + def CompileAndRun(self, OutputFile): + """编译并运行生成的C代码""" + # 获取编译命令 + CompileCmd = self.Args.get('CompileCommand', DEFAULT_COMPILE_COMMAND) + CompileFlags = self.Args.get('CompileFlags', DEFAULT_COMPILE_FLAGS) + + # 构建编译命令 + FullCompileCmd = f'{CompileCmd} {CompileFlags} {OutputFile} -o {OutputFile}.exe' + print(f'Compiling: {FullCompileCmd}') + + # 执行编译命令 + try: + CompileResult = ExecuteCommand(FullCompileCmd) + if CompileResult: + print('Compilation successful!') + + # 检查是否需要运行 + if self.Args.get('Run', False): + RunArgs = self.Args.get('RunArgs', '') + RunCmd = f'{OutputFile}.exe {RunArgs}'.strip() + print(f'Running: {RunCmd}') + + # 执行运行命令 + RunResult = ExecuteCommand(RunCmd) + if RunResult: + print('Execution output:') + print(RunResult.stdout) + if RunResult.stderr: + print('Execution errors:') + print(RunResult.stderr) + except Exception as e: + print(f'{ERROR_MESSAGES["COMPILE_FAILED"]}: {e}') + + def WriteDebugInfo(self, content): + """写入调试信息到指定文件""" + # 获取调试文件路径 + if 'Debug' in self.Args: + DebugFile = self.Args['Debug'] + else: + DebugFile = self.Args.get('Output', '').replace('.c', '.p2c') + + if DebugFile: + AppendFileContent(DebugFile, content) + + def PythonToC(self, InputFile, OutputFile): + """Python到C的转换""" + # 获取编码参数 + encoding = self.Args.get('Encoding', 'utf-8') + + # 设置调试文件路径(使用 .p2c 扩展名) + if 'Debug' in self.Args: + DebugFile = self.Args['Debug'] + else: + # 默认使用 .p2c 文件 + DebugFile = OutputFile.replace('.c', '.p2c') + + # 设置翻译器的调试文件 + self.translator.SetDebugFile(DebugFile) + + # 先清空调试文件 + with open(DebugFile, 'w', encoding=encoding) as f: + f.write('') + + # 解析辅助文件,提取符号信息 + if self.HelperFiles: + self.translator.ParseHelperFiles(self.HelperFiles, encoding) + + # 加载注解文件,提取类型定义 + if self.AnnotationFiles: + self.translator.LoadAnnotationFiles(self.AnnotationFiles) + + # 获取编码参数 + encoding = self.Args.get('Encoding', 'utf-8') + with open(InputFile, 'r', encoding=encoding) as F: + Content = F.read() + + # 保存原始代码行 + self.translator.OriginalLines = Content.split('\n') + self.translator.Content = Content + + # 解析Python代码为AST + Tree = ast.parse(Content) + + # 解析文件以提取类型信息(用于 EmbeddedAssignments) + self.translator.ParsePythonFile(InputFile, encoding) + + # 写入AST树信息(压缩格式) + with open(DebugFile, 'a', encoding=encoding) as f: + f.write('=== AST Tree (Compact) ===\n') + f.write(ast.dump(Tree)) + f.write('\n\n') + + Target = 'llvm' + CCode = self.translator.GenerateCCode(Tree, target=Target) + + import datetime + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + filename = os.path.basename(OutputFile) + + encoding = self.Args.get('Encoding', 'utf-8') + with open(OutputFile, 'w', encoding=encoding) as F: + F.write(CCode) + F.write('\n') + + def CToPython(self, InputFile, OutputFile, HeaderFiles): + """C到Python的转换(暂时禁用)""" + print("C到Python的转换功能暂时禁用,请使用Python到C的转换功能。") + + def AddSymbol(self, SymbolFiles): + """添加符号文件 + + Args: + SymbolFiles: 符号文件或符号文件列表 + """ + if isinstance(SymbolFiles, list): + self.SymbolFiles.extend(SymbolFiles) + else: + self.SymbolFiles.append(SymbolFiles) + + # 收集文件路径和编码 + HelperFiles = [] + encodings = [] + for SymbolFile in self.SymbolFiles: + FilePath = SymbolFile.FilePath + encoding = SymbolFile.encoding + if FilePath: + HelperFiles.append(FilePath) + encodings.append(encoding) + + # 解析辅助文件 + if HelperFiles: + # 暂时使用第一个文件的编码 + encoding = encodings[0] if encodings else 'utf-8' + self.translator.ParseHelperFiles(HelperFiles, encoding) + + def Convert(self, OutputFilename=None, SourceFilename=None, target='llvm'): + """转换代码 + + Args: + OutputFilename: 输出文件名(用于模板渲染) + SourceFilename: 源文件路径(用于设置CurrentFile,影响导入模块的查找) + target: 目标代码类型,仅支持 'llvm' + + Returns: + 如果debug是字符串,则返回生成的代码 + 如果debug是True,则返回生成的代码和调试信息 + """ + if not self.code: + print('Error: No code provided') + return None + + from lib.core.Handles.HandlesImports import ImportHandle + ImportHandle._struct_Load_cache.clear() + + # 如果提供了 SourceFilename,先设置 CurrentFile + # 这样导入模块时会相对于源文件所在目录查找 + if SourceFilename: + self.translator.CurrentFile = SourceFilename + + # 加载注解文件,提取类型定义 + if self.AnnotationFiles: + self.translator.LoadAnnotationFiles(self.AnnotationFiles) + + # 保存原始代码行 + self.translator.OriginalLines = self.code.split('\n') + + # 解析Python代码为AST + Tree = ast.parse(self.code) + + # 从源代码直接预扫描 import 语句,注册别名 + # 注意:不能依赖 Tree 中的 import 节点,因为 ParsePythonFile 可能修改了 AST + if not getattr(self.translator, '_ImportAliases', None): + self.translator._ImportAliases = {} + if not getattr(self.translator, '_ImportedModules', None): + self.translator._ImportedModules = set() + _prescan_tree = ast.parse(self.code) + for _node in ast.iter_child_nodes(_prescan_tree): + if isinstance(_node, ast.Import): + for _alias in _node.names: + _name = _alias.name + if _name in ('c', 't'): + continue + self.translator._ImportedModules.add(_name) + if _alias.asname: + self.translator._ImportAliases[_alias.asname] = _name + elif isinstance(_node, ast.ImportFrom): + _module_name = _node.module + if _module_name and _module_name not in ('c', 't'): + self.translator._ImportedModules.add(_module_name) + for _alias in _node.names: + if _alias.asname: + self.translator._ImportAliases[_alias.asname] = f"{_module_name}.{_alias.name}" + + # 解析代码以提取类型信息(用于 EmbeddedAssignments 和 TypedefAssignments) + # 创建临时文件路径用于解析 + import tempfile + import os + with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as f: + f.write(self.code) + TempFile = f.name + try: + # UpdateCurrentFile=False 表示不修改 CurrentFile + if SourceFilename: + self.translator.ParsePythonFile(TempFile, UpdateCurrentFile=False) + else: + self.translator.ParsePythonFile(TempFile) + finally: + os.unlink(TempFile) + + import datetime + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + if self.triple: + self.translator.triple = self.triple + if self.datalayout: + self.translator.datalayout = self.datalayout + + # 生成代码 + code = self.translator.GenerateCCode(Tree, target='llvm') + filename = os.path.basename(OutputFilename) if OutputFilename else 'generated.ll' + + # 处理调试信息 + if isinstance(self.config.debug, str): + # 如果debug是字符串,写入调试信息到文件 + with open(self.config.debug, 'w', encoding='utf-8') as f: + f.write('=== Symbol Table ===\n') + f.write(str(self.translator.SymbolTable) + '\n\n') + f.write('=== AST Tree ===\n') + f.write(ast.dump(Tree, indent=2) + '\n\n') + f.write('=== Export Table ===\n') + f.write(self.translator.Exportable.to_json() + '\n\n') + f.write('=== Generated Code ===\n') + f.write(code + '\n') + return code + elif self.config.debug: + # 如果debug是True,返回生成的代码和调试信息 + DebugInfo = { + 'SymbolTable': self.translator.SymbolTable, + 'ast_tree': ast.dump(Tree, indent=2), + 'Exportable': self.translator.Exportable.to_dict(), + 'generated_code': code + } + return code, DebugInfo + else: + # 如果debug是False,只返回生成的代码 + return code + + def Run(self): + """主运行函数""" + # 检查是否有命令行参数 + if len(sys.argv) > 1: + # 有命令行参数,使用 ParseArgs 方法解析 + self.ParseArgs() + + # 检查是否有预处理符号文件的请求 + if 'PreSym' in self.Args: + PresymConfig = self.Args['PreSym'] + InputFile = PresymConfig['input'] + OutputFile = PresymConfig['output'] + DebugFile = PresymConfig['debug'] + + # 获取编码参数 + encoding = self.Args.get('Encoding', 'utf-8') + + # 推断文件类型 + FileType = 'py' if InputFile.endswith('.py') else 'c' if InputFile.endswith('.c') else None + + # 创建 SymbolFile 对象,传入编码参数 + SymbolFile = SymbolFile(file=InputFile, type=FileType, encoding=encoding) + + # 调用 PreProcessSymbol + if DebugFile: + BinaryData, DebugInfo = TransPyC.PreProcessSymbol(SymbolFile, debug=True) + # 写入调试文件 + with open(DebugFile, 'w', encoding=encoding) as f: + f.write(DebugInfo) + print(f"Debug info written to: {DebugFile}") + else: + BinaryData = TransPyC.PreProcessSymbol(SymbolFile, debug=False) + + # 写入二进制符号文件 + with open(OutputFile, 'wb') as f: + f.write(BinaryData) + + print(f"Symbol file generated: {OutputFile}") + return + + InputFile = self.Args['Input'] + OutputFile = self.Args['Output'] + else: + # 没有命令行参数,使用默认的测试文件名称 + InputFile = DEFAULT_INPUT_FILE + OutputFile = DEFAULT_OUTPUT_FILE + print('Using default test files: test.py -> test.c') + + FileType = DetectFileType(InputFile) + + if FileType == '.py': + self.PythonToC(InputFile, OutputFile) + # 检查是否需要编译和运行 + if 'CompileCommand' in self.Args or self.Args.get('Run', False): + self.CompileAndRun(OutputFile) + elif FileType == '.c': + self.CToPython(InputFile, OutputFile, self.HeaderFiles) + else: + print(f'Error: Unsupported file type {FileType}') + sys.exit(1) diff --git a/lib/Shell/__init__.py b/lib/Shell/__init__.py new file mode 100644 index 0000000..ffec9e5 --- /dev/null +++ b/lib/Shell/__init__.py @@ -0,0 +1,6 @@ +"""Shell 包 - TransPyC 命令行入口""" +from lib.Shell.Serializer import SerializeSymbolTable, deSerializeSymbolTable, SymbolFile +from lib.Shell.Config import Config +from lib.Shell.TransPyC import TransPyC + +__all__ = ['SerializeSymbolTable', 'deSerializeSymbolTable', 'SymbolFile', 'Config', 'TransPyC'] diff --git a/lib/StubGen/Config.py b/lib/StubGen/Config.py new file mode 100644 index 0000000..fae30bc --- /dev/null +++ b/lib/StubGen/Config.py @@ -0,0 +1,42 @@ +"""StubGen 配置模块""" +import json +from dataclasses import dataclass, field +from typing import List, Dict, Optional + + +@dataclass +class StubGenConfig: + """存根生成器配置""" + InputDir: Optional[str] = None + OutputDir: str = "./stubs" + InputFiles: List[str] = field(default_factory=list) + IncludePatterns: List[str] = field(default_factory=lambda: ["*.h", "*.c", "*.py"]) + ExcludePatterns: List[str] = field(default_factory=list) + TypeMappings: Dict[str, str] = field(default_factory=dict) + PreserveStructure: bool = True # 保持目录结构 + GenerateGuards: bool = True # 生成宏守卫 + verbose: bool = False + DryRun: bool = False + + @classmethod + def from_dict(cls, data: Dict) -> 'StubGenConfig': + """从字典创建配置""" + return cls( + InputDir=data.get('InputDir'), + OutputDir=data.get('OutputDir', './stubs'), + InputFiles=data.get('InputFiles', []), + IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.py']), + ExcludePatterns=data.get('ExcludePatterns', []), + TypeMappings=data.get('TypeMappings', {}), + PreserveStructure=data.get('PreserveStructure', True), + GenerateGuards=data.get('GenerateGuards', True), + verbose=data.get('verbose', False), + DryRun=data.get('DryRun', False), + ) + + @classmethod + def from_file(cls, FilePath: str) -> 'StubGenConfig': + """从 JSON 文件加载配置""" + with open(FilePath, 'r', encoding='utf-8') as f: + data = json.load(f) + return cls.from_dict(data) diff --git a/lib/StubGen/Converter.py b/lib/StubGen/Converter.py new file mode 100644 index 0000000..a808713 --- /dev/null +++ b/lib/StubGen/Converter.py @@ -0,0 +1,967 @@ +"""StubGen 转换器模块 - 将 Python 文件转换为存根格式""" +import ast +import re +from typing import List, Dict, Optional, Tuple + + +class PythonToStubConverter: + """将 Python 文件转换为存根格式""" + + # __include 别名映射表 {alias: ModuleName} + IncludeAliasMap: Dict[str, str] = {} + + # 变量排除列表 - 匹配这些模式的变量不会被添加到存根文件 + VarExcludeList: List[str] = [] + + # 宏排除列表 - 匹配这些模式的宏不会被添加到存根文件 + MacroExcludeList: List[str] = [] + + @classmethod + def SetIncludeAliasMap(cls, alias_map: Dict[str, str]): + """设置 __include 别名映射表""" + cls.IncludeAliasMap = alias_map + + @classmethod + def SetVarExcludeList(cls, exclude_list: List[str]): + """设置变量排除列表""" + cls.VarExcludeList = exclude_list + + @classmethod + def SetMacroExcludeList(cls, exclude_list: List[str]): + """设置宏排除列表""" + cls.MacroExcludeList = exclude_list + + @classmethod + def _ShouldExcludeVar(cls, VarName: str) -> bool: + """检查变量是否应该被排除""" + import fnmatch + for pattern in cls.VarExcludeList: + if fnmatch.fnmatch(VarName, pattern): + return True + return False + + @classmethod + def _ShouldExcludeMacro(cls, MacroName: str) -> bool: + """检查宏是否应该被排除""" + import fnmatch + for pattern in cls.MacroExcludeList: + if fnmatch.fnmatch(MacroName, pattern): + return True + return False + + @staticmethod + def convert(PyContent: str, ModuleName: str) -> str: + """将 Python 代码转换为存根格式""" + lines = PyContent.split('\n') + StubLines = [] + + # 添加文件头 + StubLines.append('"""') + StubLines.append(f'Auto-generated Python stub file from {ModuleName}.py') + StubLines.append(f'Module: {ModuleName}') + StubLines.append('"""') + StubLines.append('') + + # 解析 Python 代码,检查是否已经导入了 t 和 c + import ast + HasImportT = False + HasImportC = False + try: + tree = ast.parse(PyContent) + for node in tree.body: + if isinstance(node, ast.Import): + for alias in node.names: + if alias.name == 't': + HasImportT = True + elif alias.name == 'c': + HasImportC = True + except: + pass + + # 添加默认导入(如果源代码中没有) + if not HasImportT: + StubLines.append('import t') + if not HasImportC: + StubLines.append('import c') + if not HasImportT or not HasImportC: + StubLines.append('') + + # 添加 c.CPragma("once") + # StubLines.append('c.CPragma("once")') + StubLines.append('') + + # 生成文件级别宏守卫名称 + #FileGuardName = f'__{ModuleName.upper()}_DEFINE__' + + # 添加文件开头宏守卫 + #StubLines.append(f'c.CIfndef({FileGuardName})') + #StubLines.append(f'{FileGuardName}: t.CDefine') + #StubLines.append('') + + # 解析 Python 代码,提取类型定义 + try: + tree = ast.parse(PyContent) + + # 第一遍扫描:收集 Postdefinition 变量 + PostdefVars = {} # {ClassName: [(VarName, TypeStr, node), ...]} + for node in tree.body: + if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + TypeStr = PythonToStubConverter._GetTypeString(node.annotation) + # 检查是否是 Postdefinition 类型 + if 't.Postdefinition' in TypeStr: + # 提取引用的类名 + ClassName = PythonToStubConverter._ExtractPostdefClass(node.annotation) + if ClassName: + if ClassName not in PostdefVars: + PostdefVars[ClassName] = [] + PostdefVars[ClassName].append((node.target.id, TypeStr, node)) + + # 按原始顺序处理节点,保持代码的原始顺序 + PrevType = None # 记录前一个节点的类型 + + for node in tree.body: + CurrentType = None + + if isinstance(node, ast.ClassDef): + CurrentType = 'class' + # 如果前一个不是类,添加空行分隔 + if PrevType is not None and PrevType != 'class': + StubLines.append('') + # 检查是否有对应的 Postdefinition 变量 + ClassPostdefs = PostdefVars.get(node.name, []) + ClassLines = PythonToStubConverter._ConvertClass( + node, SourceLines=lines, PostdefVars=ClassPostdefs + ) + StubLines.extend(ClassLines) + elif isinstance(node, ast.FunctionDef): + CurrentType = 'function' + # 如果前一个是类或者是第一个函数,添加空行分隔 + if PrevType == 'class' or (PrevType is not None and PrevType != 'function'): + StubLines.append('') + FuncLines = PythonToStubConverter._ConvertFunction(node, SourceLines=lines) + StubLines.extend(FuncLines) + StubLines.append('') # 函数后空行 + elif isinstance(node, ast.AnnAssign): + CurrentType = 'variable' + # 跳过 Postdefinition 变量(已经在类中处理) + TypeStr = PythonToStubConverter._GetTypeString(node.annotation) + if 't.Postdefinition' in TypeStr: + continue + # 检查是否带有 t.CStatic 标志,如果有则不排除 + HasStatic = 't.CStatic' in TypeStr + # 检查变量是否应该被排除 + ShouldExclude = False + if isinstance(node.target, ast.Name) and not HasStatic: + VarName = node.target.id + if PythonToStubConverter._ShouldExcludeVar(VarName): + ShouldExclude = True + if ShouldExclude: + continue + # 如果前一个不是变量,添加空行分隔 + if PrevType is not None and PrevType != 'variable': + StubLines.append('') + VarLines = PythonToStubConverter._ConvertVariable(node, SourceLines=lines) + # 移除多余的空行 + VarLines = [line for line in VarLines if line.strip()] + StubLines.extend(VarLines) + elif isinstance(node, ast.Import): + # 处理导入语句 + CurrentType = 'import' + ImportStr = PythonToStubConverter._GetImportString(node, SourceLines=lines) + if ImportStr: + if PrevType is not None and PrevType != 'import': + StubLines.append('') + StubLines.append(ImportStr) + elif isinstance(node, ast.Assign): + CurrentType = 'variable' + # 处理模块级别的全局变量(无类型标注) + if PrevType is not None and PrevType != 'variable': + StubLines.append('') + AssignLines = PythonToStubConverter._ConvertGlobalAssign(node) + StubLines.extend(AssignLines) + elif isinstance(node, ast.ImportFrom): + # 处理 from ... import ... 语句 + CurrentType = 'import' + ImportStr = PythonToStubConverter._GetImportFromString(node, SourceLines=lines) + if ImportStr: + if PrevType is not None and PrevType != 'import': + StubLines.append('') + StubLines.append(ImportStr) + elif isinstance(node, ast.Expr): + # 处理模块级别的宏调用,如 c.CIf(...), c.CEndif() + ExprStr = PythonToStubConverter._GetExprString(node.value) + if ExprStr: + CurrentType = 'macro' + StubLines.append(ExprStr) + StubLines.append('') # 宏后空行 + elif isinstance(node, ast.If): + # 处理模块级别的 if 宏条件,如 if c.CIf(FF_MULTI_PARTITION): + IfStr = PythonToStubConverter._GetModuleIfMacroString(node) + if IfStr: + CurrentType = 'macro' + StubLines.append(IfStr) + StubLines.append('') # 宏后空行 + + if CurrentType: + PrevType = CurrentType + + # 添加文件结尾宏守卫 + #StubLines.append('') + #StubLines.append('c.CEndif()') + + except SyntaxError as e: + # 如果解析失败,添加注释说明 + StubLines.append(f'# Warning: Failed to parse Python code: {e}') + StubLines.append('# Original content:') + StubLines.append('"""') + StubLines.append(PyContent[:1000]) # 只显示前1000字符 + StubLines.append('"""') + + return '\n'.join(StubLines) + + @staticmethod + def _ConvertClass(node: ast.ClassDef, SourceLines: List[str] = None, PostdefVars: List[Tuple[str, str, ast.AnnAssign]] = None, indent: int = 0) -> List[str]: + """转换类定义 + + Args: + node: 类定义节点 + SourceLines: 源代码行列表 + PostdefVars: Postdefinition 变量列表 [(VarName, TypeStr, node), ...] + indent: 缩进级别(用于嵌套类) + """ + lines = [] + PostdefVars = PostdefVars or [] + IndentStr = ' ' * indent + + # 处理类装饰器 + for decorator in node.decorator_list: + DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) + if DecoratorStr: + lines.append(f'{IndentStr}@{DecoratorStr}') + + # 检查是否是结构体、联合体或枚举 + BaseNames = [base.attr if isinstance(base, ast.Attribute) else base.id + for base in node.bases + if isinstance(base, (ast.Name, ast.Attribute))] + + # 保留原始基类 + if node.bases: + BaseStrs = [] + for base in node.bases: + if isinstance(base, ast.Name): + BaseStrs.append(base.id) + elif isinstance(base, ast.Attribute): + BaseStrs.append(f'{base.value.id}.{base.attr}') + elif isinstance(base, ast.Subscript): + # 处理泛型类型,如 memory_block_t[MAX_ORDER + 1] + BaseStrs.append(PythonToStubConverter._GetTypeString(base)) + ClassTypeParamStr = '' + if hasattr(node, 'type_params') and node.type_params: + param_names = [tp.name for tp in node.type_params] + ClassTypeParamStr = f'[{", ".join(param_names)}]' + if BaseStrs: + lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}({", ".join(BaseStrs)}):') + else: + lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}:') + else: + ClassTypeParamStr = '' + if hasattr(node, 'type_params') and node.type_params: + param_names = [tp.name for tp in node.type_params] + ClassTypeParamStr = f'[{", ".join(param_names)}]' + lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}:') + + # 处理类成员 + HasMembers = False + seen_member_names = set() + for item in node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + seen_member_names.add(item.target.id) + init_members = [] + for item in node.body: + if isinstance(item, ast.FunctionDef) and item.name == '__init__': + for stmt in item.body: + if (isinstance(stmt, ast.AnnAssign) + and isinstance(stmt.target, ast.Attribute) + and isinstance(stmt.target.value, ast.Name) + and stmt.target.value.id == 'self'): + init_members.append(stmt) + untyped_self_members = [] + for m_name in [m.target.attr for m in init_members if isinstance(m.target, ast.Attribute)]: + seen_member_names.add(m_name) + for item in node.body: + if isinstance(item, ast.FunctionDef): + for stmt in item.body: + if (isinstance(stmt, ast.Assign) + and len(stmt.targets) == 1 + and isinstance(stmt.targets[0], ast.Attribute) + and isinstance(stmt.targets[0].value, ast.Name) + and stmt.targets[0].value.id == 'self'): + attr_name = stmt.targets[0].attr + if attr_name not in seen_member_names: + seen_member_names.add(attr_name) + untyped_self_members.append(stmt) + for item in list(node.body) + init_members + untyped_self_members: + if isinstance(item, ast.Assign): + if (len(item.targets) == 1 + and isinstance(item.targets[0], ast.Attribute) + and isinstance(item.targets[0].value, ast.Name) + and item.targets[0].value.id == 'self'): + HasMembers = True + MemberIndent = IndentStr + ' ' + attr_name = item.targets[0].attr + if attr_name in seen_member_names: + continue + InferredType = 'int' + if item.value and isinstance(item.value, ast.Constant): + if isinstance(item.value.value, float): + InferredType = 'float' + elif isinstance(item.value.value, bool): + InferredType = 'bool' + elif isinstance(item.value.value, str): + InferredType = 'str' + lines.append(f'{MemberIndent}{attr_name}: {InferredType}') + else: + HasMembers = True + MemberIndent = IndentStr + ' ' + if SourceLines and hasattr(item, 'lineno'): + StartLine = item.lineno - 1 + EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 + for i in range(StartLine, min(EndLine, len(SourceLines))): + lines.append(MemberIndent + SourceLines[i].lstrip()) + elif isinstance(item, ast.AnnAssign): + HasMembers = True + TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + MemberIndent = IndentStr + ' ' + # 检查是否是宏变量(类型包含 t.CDefine) + if 't.CDefine' in TypeStr: + # 检查宏变量是否应该被排除 + if isinstance(item.target, ast.Name): + MacroName = item.target.id + if PythonToStubConverter._ShouldExcludeMacro(MacroName): + continue # 跳过该宏 + # 宏变量保持原样(包括赋值) + if SourceLines and hasattr(item, 'lineno'): + StartLine = item.lineno - 1 + EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 + for i in range(StartLine, min(EndLine, len(SourceLines))): + lines.append(MemberIndent + SourceLines[i].lstrip()) + else: + lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') + else: + if isinstance(item.target, ast.Attribute): + MemberName = item.target.attr + else: + MemberName = item.target.id + FinalTypeStr = TypeStr + if (isinstance(item.annotation, ast.Subscript) + and isinstance(item.annotation.value, ast.Name) + and item.annotation.value.id == 'list'): + slice_node = item.annotation.slice + has_size = False + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: + count_node = slice_node.elts[1] + if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0: + has_size = True + else: + try: + count_expr = ast.unparse(count_node) + except Exception: + count_expr = '' + if count_expr and count_expr != 'None': + has_size = True + elem_type_str = PythonToStubConverter._GetTypeString(slice_node.elts[0]) + FinalTypeStr = f'list[{elem_type_str}, {count_expr}]' + if not has_size: + elem_type_str = PythonToStubConverter._GetTypeString(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0]) + init_len = 0 + if item.value is not None: + if isinstance(item.value, ast.List): + init_len = len(item.value.elts) + elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): + init_len = len(item.value.value) + 1 + if init_len > 0: + FinalTypeStr = f'list[{elem_type_str}, {init_len}]' + else: + FinalTypeStr = f'list[{elem_type_str}, None]' + lines.append(f'{MemberIndent}{MemberName}: {FinalTypeStr}') + elif isinstance(item, ast.FunctionDef): + HasMembers = True + FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name) + lines.extend(FuncStub) + elif isinstance(item, ast.Expr): + # 处理宏调用,如 c.CIf(...), c.CEndif(), c.CElif(), c.CElse() + ExprStr = PythonToStubConverter._GetExprString(item.value) + if ExprStr: + lines.append(f'{IndentStr} {ExprStr}') + elif isinstance(item, ast.If): + # 处理 if c.CIf(...): 形式的宏条件 + IfStr = PythonToStubConverter._get_if_macro_string(item, indent=indent+1) + if IfStr: + lines.append(IfStr) + elif isinstance(item, ast.ClassDef): + # 处理嵌套类 + HasMembers = True + NestedClassLines = PythonToStubConverter._ConvertClass(item, SourceLines=SourceLines, PostdefVars=[], indent=indent+1) + # 移除嵌套类的宏守卫(因为已经在父类的宏守卫内) + FilteredLines = [] + for line in NestedClassLines: + # 跳过宏守卫相关行 + if line.strip().startswith('c.CIfndef(') or line.strip().startswith('c.CEndif()'): + continue + if ': t.CDefine' in line and '__' in line: + continue + FilteredLines.append(line) + lines.extend(FilteredLines) + + if not HasMembers: + lines.append(f'{IndentStr} pass') + + # 添加 Postdefinition 变量 + if PostdefVars: + lines.append('') + for VarName, TypeStr, _ in PostdefVars: + lines.append(f'{VarName}: {TypeStr}') + + return lines + + @staticmethod + def _ConvertFunction(node: ast.FunctionDef, indent: int = 0, SourceLines: List[str] = None, class_name: str = None) -> List[str]: + """转换函数定义""" + lines = [] + IndentStr = ' ' * indent + + # 检查是否是宏函数(返回类型包含 t.CDefine) + is_macro_func = False + if node.returns: + ReturnType = PythonToStubConverter._GetTypeString(node.returns) + if 't.CDefine' in ReturnType: + is_macro_func = True + + # 如果是宏函数,检查是否应该被排除 + if is_macro_func: + if PythonToStubConverter._ShouldExcludeMacro(node.name): + return lines # 返回空列表,排除该宏 + + # 保持原样(包括代码块) + if SourceLines: + StartLine = node.lineno - 1 + EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 + for i in range(StartLine, min(EndLine, len(SourceLines))): + lines.append(SourceLines[i]) + if lines and lines[-1].strip() and not lines[-1].rstrip().endswith(':'): + pass + else: + lines.append(f'{IndentStr} pass') + return lines + + # 处理函数装饰器 + for decorator in node.decorator_list: + DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) + if DecoratorStr: + lines.append(f'{IndentStr}@{DecoratorStr}') + + # 构建参数列表 + params = [] + for arg_idx, arg in enumerate(node.args.args): + ArgName = arg.arg + if arg.annotation: + TypeStr = PythonToStubConverter._GetTypeString(arg.annotation) + params.append(f'{ArgName}: {TypeStr}') + elif class_name and arg_idx == 0 and ArgName == 'self': + params.append(f'self: {class_name}') + else: + params.append(ArgName) + + # 处理 *args + if node.args.vararg: + ArgName = node.args.vararg.arg + if node.args.vararg.annotation: + TypeStr = PythonToStubConverter._GetTypeString(node.args.vararg.annotation) + params.append(f'*{ArgName}: {TypeStr}') + else: + params.append(f'*{ArgName}') + + # 处理 **kwargs + if node.args.kwarg: + ArgName = node.args.kwarg.arg + if node.args.kwarg.annotation: + TypeStr = PythonToStubConverter._GetTypeString(node.args.kwarg.annotation) + params.append(f'**{ArgName}: {TypeStr}') + else: + params.append(f'**{ArgName}') + + ParamStr = ', '.join(params) + + # 返回类型 - 保持原始类型(不添加t.State) + if node.returns: + ReturnType = PythonToStubConverter._GetTypeString(node.returns) + else: + ReturnType = 't.CInt' + + TypeParamStr = '' + if hasattr(node, 'type_params') and node.type_params: + param_names = [tp.name for tp in node.type_params] + TypeParamStr = f'[{", ".join(param_names)}]' + + lines.append(f'{IndentStr}def {node.name}{TypeParamStr}({ParamStr}) -> {ReturnType}: pass') + return lines + + @staticmethod + def _ConvertVariable(node: ast.AnnAssign, SourceLines: List[str] = None) -> List[str]: + """转换变量定义""" + lines = [] + if isinstance(node.target, ast.Name): + VarName = node.target.id + TypeStr = PythonToStubConverter._GetTypeString(node.annotation) + # 检查是否是宏变量(类型包含 t.CDefine) + if 't.CDefine' in TypeStr: + # 检查宏变量是否应该被排除 + if PythonToStubConverter._ShouldExcludeMacro(VarName): + return lines # 返回空列表,排除该宏 + # 宏变量保持原样(包括赋值) + if SourceLines and hasattr(node, 'lineno'): + StartLine = node.lineno - 1 + EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 + for i in range(StartLine, min(EndLine, len(SourceLines))): + lines.append(SourceLines[i]) + else: + lines.append(f'{VarName}: {TypeStr}') + return lines + # 非宏变量:不加 t.State + # 含有 typedef 的变量不加 extern,普通变量需要加 extern + has_typedef = 't.CTypedef' in TypeStr or 'CTypedef' in TypeStr + if has_typedef and node.value is not None: + ValueTypeStr = PythonToStubConverter._GetTypeString(node.value) + lines.append(f'{VarName}: {TypeStr} = {ValueTypeStr}') + else: + if not has_typedef and 't.CExtern' not in TypeStr and 't.CStatic' not in TypeStr: + TypeStr = f't.CExtern | {TypeStr}' + lines.append(f'{VarName}: {TypeStr}') + return lines + + @staticmethod + def _ConvertGlobalAssign(node: ast.Assign) -> List[str]: + """转换模块级别的全局变量(无类型标注)""" + lines = [] + if not node.targets or not isinstance(node.targets[0], ast.Name): + return lines + + VarName = node.targets[0].id + + # 跳过私有变量(以下划线开头) + if VarName.startswith('_'): + return lines + + # 从值推断类型 + inferred_type = PythonToStubConverter._InferTypeFromValue(node.value) + if inferred_type: + lines.append(f'{VarName}: {inferred_type}') + else: + lines.append(f'{VarName}: t.CInt') + + return lines + + @staticmethod + def _InferTypeFromValue(value: ast.AST) -> str: + """从值推断 C 类型""" + if isinstance(value, ast.Constant): + if isinstance(value.value, int): + return 't.CInt' + elif isinstance(value.value, float): + return 't.CDouble' + elif isinstance(value.value, str): + return 't.CCharPtr' + elif isinstance(value.value, bool): + return 't.CInt' + elif isinstance(value, ast.List): + return 't.CVoidPtr' + elif isinstance(value, ast.Dict): + return 't.CVoidPtr' + elif isinstance(value, ast.Name): + return 't.CInt' + elif isinstance(value, ast.BinOp): + left_type = PythonToStubConverter._InferTypeFromValue(value.left) + if left_type: + return left_type + return 't.CInt' + elif isinstance(value, ast.Call): + # 函数调用返回值,假设为指针类型 + if isinstance(value.func, ast.Name): + func_name = value.func.id + if func_name == 'malloc': + return 't.CVoidPtr' + elif func_name in ('ctypes.cast', 'cast'): + return 't.CVoidPtr' + return 't.CVoidPtr' + return None + + @staticmethod + def _GetTypeString(annotation: ast.AST) -> str: + """获取类型字符串""" + if isinstance(annotation, ast.Name): + return annotation.id + elif isinstance(annotation, ast.Attribute): + if isinstance(annotation.value, ast.Name): + return f'{annotation.value.id}.{annotation.attr}' + else: + # 处理嵌套属性访问,如 t.attr.packed + ParentStr = PythonToStubConverter._GetTypeString(annotation.value) + return f'{ParentStr}.{annotation.attr}' + elif isinstance(annotation, ast.Subscript): + base = PythonToStubConverter._GetTypeString(annotation.value) + if isinstance(annotation.slice, ast.Tuple): + slice_strs = [PythonToStubConverter._GetTypeString(e) for e in annotation.slice.elts] + SliceStr = ', '.join(slice_strs) + else: + SliceStr = PythonToStubConverter._GetTypeString(annotation.slice) + return f'{base}[{SliceStr}]' + elif isinstance(annotation, ast.BinOp): + # 处理 BinOp,如 t.CExtern | fd_table.__set_default__(...) + left = annotation.left + right = annotation.right + + # 检查右侧是否是 __set_default__ 调用 + if isinstance(right, ast.Call) and isinstance(right.func, ast.Attribute) and right.func.attr in ('__set_default__', '__set_default'): + # 去除 __set_default__,保留左侧,右侧替换为函数名部分 + LeftStr = PythonToStubConverter._GetTypeString(left) + RightStr = PythonToStubConverter._GetTypeString(right.func.value) + if isinstance(annotation.op, ast.BitOr): + return f'{LeftStr} | {RightStr}' + + LeftStr = PythonToStubConverter._GetTypeString(left) + RightStr = PythonToStubConverter._GetTypeString(right) + if isinstance(annotation.op, ast.BitOr): + return f'{LeftStr} | {RightStr}' + elif isinstance(annotation.op, ast.Add): + return f'{LeftStr} + {RightStr}' + elif isinstance(annotation.op, ast.Sub): + return f'{LeftStr} - {RightStr}' + elif isinstance(annotation.op, ast.Mult): + return f'{LeftStr} * {RightStr}' + elif isinstance(annotation.op, ast.Div): + return f'{LeftStr} / {RightStr}' + elif isinstance(annotation.op, ast.Mod): + return f'{LeftStr} % {RightStr}' + elif isinstance(annotation, ast.UnaryOp): + if isinstance(annotation.op, ast.Not): + operand = PythonToStubConverter._GetTypeString(annotation.operand) + return f'not {operand}' + elif isinstance(annotation.op, ast.Invert): + operand = PythonToStubConverter._GetTypeString(annotation.operand) + return f'~{operand}' + elif isinstance(annotation.op, ast.USub): + operand = PythonToStubConverter._GetTypeString(annotation.operand) + return f'-{operand}' + elif isinstance(annotation, ast.Compare): + # 处理比较操作,如 FF_MAX_SS != FF_MIN_SS + left = PythonToStubConverter._GetTypeString(annotation.left) + comparators = [PythonToStubConverter._GetTypeString(c) for c in annotation.comparators] + ops = [] + for op in annotation.ops: + if isinstance(op, ast.Eq): + ops.append('==') + elif isinstance(op, ast.NotEq): + ops.append('!=') + elif isinstance(op, ast.Lt): + ops.append('<') + elif isinstance(op, ast.LtE): + ops.append('<=') + elif isinstance(op, ast.Gt): + ops.append('>') + elif isinstance(op, ast.GtE): + ops.append('>=') + else: + ops.append('?') + result = left + for i, op in enumerate(ops): + result += f' {op} {comparators[i]}' + return result + elif isinstance(annotation, ast.Constant): + return repr(annotation.value) + elif isinstance(annotation, ast.Index): + return PythonToStubConverter._GetTypeString(annotation.value) + elif isinstance(annotation, ast.List): + # 处理列表,如 [MAX_FILE_DESCRIPTORS] + elements = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] + return f'[{", ".join(elements)}]' + elif isinstance(annotation, ast.Call): + # 处理函数调用形式的类型注解,如 t.Postdefinition(xxa) 或 callable(t.CVoid, app_id = t.CInt) + # 如果是 __set_default__ 调用,只返回函数名部分 + if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'): + return PythonToStubConverter._GetTypeString(annotation.func.value) + + FuncStr = PythonToStubConverter._GetTypeString(annotation.func) + ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in annotation.args]) + # 处理关键字参数 + keywords_str = ', '.join([f'{kw.arg} = {PythonToStubConverter._GetTypeString(kw.value)}' for kw in annotation.keywords]) + # 合并位置参数和关键字参数 + if ArgsStr and keywords_str: + return f'{FuncStr}({ArgsStr}, {keywords_str})' + elif keywords_str: + return f'{FuncStr}({keywords_str})' + else: + return f'{FuncStr}({ArgsStr})' + return 't.CVoid' + + @staticmethod + def _ExtractPostdefClass(annotation: ast.AST) -> Optional[str]: + """从 Postdefinition 类型注解中提取类名 + + 例如:t.Postdefinition(__buddy_system) -> '__buddy_system' + t.Postdefinition(xxx) | t.CTypedef -> 'xxx' + """ + # 处理 BinOp (如: t.Postdefinition(xxx) | t.CTypedef) + if isinstance(annotation, ast.BinOp): + # 递归检查左操作数 + left_result = PythonToStubConverter._ExtractPostdefClass(annotation.left) + if left_result: + return left_result + # 递归检查右操作数 + right_result = PythonToStubConverter._ExtractPostdefClass(annotation.right) + if right_result: + return right_result + return None + + # 处理函数调用 (如: t.Postdefinition(__buddy_system)) + if isinstance(annotation, ast.Call): + FuncStr = PythonToStubConverter._GetTypeString(annotation.func) + if FuncStr == 't.Postdefinition' and annotation.args: + # 提取第一个参数 + first_arg = annotation.args[0] + if isinstance(first_arg, ast.Name): + return first_arg.id + elif isinstance(first_arg, ast.Attribute): + return f'{first_arg.value.id}.{first_arg.attr}' + + return None + + @staticmethod + def _GetImportString(node: ast.Import, SourceLines: List[str] = None) -> str: + """获取导入语句字符串""" + parts = [] + IncludeAliasMap = PythonToStubConverter.IncludeAliasMap + + for alias in node.names: + ModuleName = alias.name + # 检查是否是 __include.xxx 格式的导入 + if ModuleName.startswith('__include.'): + # 提取别名(xxx 部分) + SubModule = ModuleName[len('__include.'):] + if SubModule in IncludeAliasMap: + # 替换为实际模块路径 + RealModule = IncludeAliasMap[SubModule] + if alias.asname: + parts.append(f'{RealModule} as {alias.asname}') + else: + parts.append(f'{RealModule} as {SubModule}') + else: + # 不在映射表中,保持原样 + if alias.asname: + parts.append(f'{ModuleName} as {alias.asname}') + else: + parts.append(ModuleName) + else: + if alias.asname: + parts.append(f'{alias.name} as {alias.asname}') + else: + parts.append(alias.name) + + result = f'import {", ".join(parts)}' + + # 提取并保留注释 + if SourceLines and hasattr(node, 'lineno'): + LineIdx = node.lineno - 1 + if 0 <= LineIdx < len(SourceLines): + line = SourceLines[LineIdx] + CommentMatch = re.search(r'#.*$', line) + if CommentMatch: + result += ' ' + CommentMatch.group(0) + + return result + + @staticmethod + def _GetImportFromString(node: ast.ImportFrom, SourceLines: List[str] = None) -> str: + """获取 from ... import ... 语句字符串""" + module = node.module or '' + parts = [] + IncludeAliasMap = PythonToStubConverter.IncludeAliasMap + + # 处理相对导入 (from . import xxx 或 from ..package import xxx) + if node.level > 0: + if module: + if node.level == 1: + full_module = f'.{module}' + else: + full_module = '.' * node.level + module + else: + full_module = '.' * node.level + for alias in node.names: + if alias.asname: + parts.append(f'{alias.name} as {alias.asname}') + else: + parts.append(alias.name) + return f'from {full_module} import {", ".join(parts)}' + + # 提取注释(在生成结果前获取) + comment = '' + if SourceLines and hasattr(node, 'lineno'): + LineIdx = node.lineno - 1 + if 0 <= LineIdx < len(SourceLines): + line = SourceLines[LineIdx] + CommentMatch = re.search(r'#.*$', line) + if CommentMatch: + comment = ' ' + CommentMatch.group(0) + + # 检查是否是 from __include import xxx 格式 + if module == '__include': + for alias in node.names: + name = alias.name + if name in IncludeAliasMap: + # 替换为实际模块路径 + RealModule = IncludeAliasMap[name] + if alias.asname: + parts.append(f'import {RealModule} as {alias.asname}{comment}') + else: + parts.append(f'import {RealModule} as {name}{comment}') + else: + # 不在映射表中,保持原样 + if alias.asname: + parts.append(f'from {module} import {name} as {alias.asname}{comment}') + else: + parts.append(f'from {module} import {name}{comment}') + return '\n'.join(parts) + + # 普通 from ... import ... 语句 + for alias in node.names: + if alias.asname: + parts.append(f'{alias.name} as {alias.asname}') + else: + parts.append(alias.name) + return f'from {module} import {", ".join(parts)}{comment}' + + @staticmethod + def _GetDecoratorString(decorator: ast.AST) -> str: + """获取装饰器字符串""" + if isinstance(decorator, ast.Name): + return decorator.id + elif isinstance(decorator, ast.Attribute): + if isinstance(decorator.value, ast.Name): + return f'{decorator.value.id}.{decorator.attr}' + return decorator.attr + elif isinstance(decorator, ast.Call): + # 处理带参数的装饰器,如 @c.Attribute(t.attr.packed) + FuncStr = PythonToStubConverter._GetDecoratorString(decorator.func) + ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args]) + return f'{FuncStr}({ArgsStr})' + return '' + + @staticmethod + def _GetExprString(expr: ast.AST) -> str: + """获取表达式字符串(用于宏调用)""" + if isinstance(expr, ast.Call): + # 处理函数调用,如 c.CIf(...), c.CEndif(), c.CUndef(...), c.CPragma(...) + FuncStr = PythonToStubConverter._GetDecoratorString(expr.func) + if FuncStr and ('CIf' in FuncStr or 'CEndif' in FuncStr or 'CElif' in FuncStr or 'CElse' in FuncStr or 'CUndef' in FuncStr or 'CPragma' in FuncStr): + ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args]) + return f'{FuncStr}({ArgsStr})' if ArgsStr else f'{FuncStr}()' + return '' + + @staticmethod + def _get_if_macro_string(node: ast.If, indent: int = 1) -> str: + """获取类内部的 if 宏字符串(如 if c.CIf(...):)""" + IndentStr = ' ' * indent + InnerIndent = ' ' * (indent + 1) + # 检查条件是否是宏调用 + if isinstance(node.test, ast.Call): + FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) + if FuncStr and 'CIf' in FuncStr: + ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) + result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] + # 处理 if 体内的语句 + for item in node.body: + if isinstance(item, ast.AnnAssign): + TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + result.append(f'{InnerIndent}{item.target.id}: {TypeStr}') + elif isinstance(item, ast.Expr): + ExprStr = PythonToStubConverter._GetExprString(item.value) + if ExprStr: + result.append(f'{InnerIndent}{ExprStr}') + return '\n'.join(result) + return '' + + @staticmethod + def _GetModuleIfMacroString(node: ast.If) -> str: + """获取模块级别的 if 宏字符串(如 if c.CIf(FF_MULTI_PARTITION):)""" + return PythonToStubConverter._ProcessIfMacro(node, indent=0) + + @staticmethod + def _ProcessIfMacro(node: ast.If, indent: int = 0) -> str: + """处理 if 宏节点,支持 elif 和 else""" + IndentStr = ' ' * indent + + # 检查条件是否是宏调用 + if isinstance(node.test, ast.Call): + FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) + if FuncStr and 'CIf' in FuncStr: + ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) + result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] + # 处理 if 体内的语句 + for item in node.body: + result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) + + # 处理 elif 和 else + current = node + while current.orelse: + if len(current.orelse) == 1 and isinstance(current.orelse[0], ast.If): + # elif 情况 + elif_node = current.orelse[0] + if isinstance(elif_node.test, ast.Call): + ElifFuncStr = PythonToStubConverter._GetDecoratorString(elif_node.test.func) + if ElifFuncStr and 'CIf' in ElifFuncStr: + ElifArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in elif_node.test.args]) + result.append(f'{IndentStr}elif {ElifFuncStr}({ElifArgsStr}):' if ElifArgsStr else f'{IndentStr}elif {ElifFuncStr}():') + for item in elif_node.body: + result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) + current = elif_node + continue + break + else: + # else 情况 + result.append(f'{IndentStr}else:') + for item in current.orelse: + result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) + break + + return '\n'.join(result) + return '' + + @staticmethod + def _ProcessMacroBodyItem(item: ast.AST, indent: int = 0) -> list: + """处理宏体内的单个语句""" + IndentStr = ' ' * indent + result = [] + + if isinstance(item, ast.ClassDef): + class_stub = PythonToStubConverter._ConvertClass(item) + for line in class_stub: + if line.strip(): + result.append(f'{IndentStr}{line}') + else: + result.append(line) + elif isinstance(item, ast.FunctionDef): + FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent) + result.extend(FuncStub) + elif isinstance(item, ast.AnnAssign): + TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + result.append(f'{IndentStr}{item.target.id}: {TypeStr}') + elif isinstance(item, ast.Expr): + ExprStr = PythonToStubConverter._GetExprString(item.value) + if ExprStr: + result.append(f'{IndentStr}{ExprStr}') + elif isinstance(item, ast.If): + # 处理嵌套的 if 宏 + NestedIf = PythonToStubConverter._ProcessIfMacro(item, indent=indent) + if NestedIf: + result.append(NestedIf) + + return result diff --git a/lib/StubGen/Generator.py b/lib/StubGen/Generator.py new file mode 100644 index 0000000..111b87d --- /dev/null +++ b/lib/StubGen/Generator.py @@ -0,0 +1,311 @@ +"""StubGen 生成器模块 - 存根生成器主类和命令行入口""" +import sys +import os +import re +import argparse +import logging +from pathlib import Path +from typing import List, Tuple + +from lib.core.stub_generator import CHeaderParser, PythonStubGenerator, CTypeMapper +from lib.StubGen.Config import StubGenConfig +from lib.StubGen.Converter import PythonToStubConverter + + +class StubGen: + """存根生成器主类""" + + def __init__(self, config: StubGenConfig): + self.config = config + self.logger = self._SetupLogger() + self.GeneratedFiles: List[str] = [] + self.FailedFiles: List[str] = [] + + # 应用自定义类型映射 + if config.TypeMappings: + CTypeMapper.BASIC_TYPE_MAP.update(config.TypeMappings) + + def _SetupLogger(self) -> logging.Logger: + """设置日志""" + logger = logging.getLogger('StubGen') + logger.setLevel(logging.DEBUG if self.config.verbose else logging.INFO) + + if not logger.handlers: + handler = logging.StreamHandler(sys.stdout) + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + handler.setFormatter(formatter) + logger.addHandler(handler) + + return logger + + def FindInputFiles(self) -> List[Tuple[str, str]]: + """查找输入文件,返回 (文件路径, 相对路径) 列表""" + files = [] + + # 添加显式指定的文件 + for FilePath in self.config.InputFiles: + if os.path.exists(FilePath): + RelPath = os.path.relpath(FilePath, self.config.InputDir or '.') + files.append((FilePath, RelPath)) + else: + self.logger.warning(f"Input file not found: {FilePath}") + + # 从输入目录查找 + if self.config.InputDir and os.path.exists(self.config.InputDir): + InputPath = Path(self.config.InputDir) + for pattern in self.config.IncludePatterns: + for FilePath in InputPath.rglob(pattern): + # 检查是否在排除列表中 + excluded = False + RelPath = os.path.relpath(str(FilePath), self.config.InputDir) + + for exclude_pattern in self.config.ExcludePatterns: + if FilePath.match(exclude_pattern) or RelPath == exclude_pattern: + excluded = True + break + + if not excluded: + files.append((str(FilePath), RelPath)) + + # 去重并保持顺序 + seen = set() + UniqueFiles = [] + for FilePath, RelPath in files: + key = FilePath + if key not in seen: + seen.add(key) + UniqueFiles.append((FilePath, RelPath)) + + return UniqueFiles + + def _GenerateGuardName(self, FilePath: str) -> str: + """生成宏守卫名称""" + # 获取文件名(不含扩展名) + BaseName = os.path.splitext(os.path.basename(FilePath))[0] + + # 转换为大写,替换特殊字符为下划线 + guard = re.sub(r'[^a-zA-Z0-9_]', '_', BaseName).upper() + guard = re.sub(r'_+', '_', guard) # 合并多个下划线 + guard = guard.strip('_') + + return f'{guard}_DEFINE_H' + + def _GetOutputPath(self, RelPath: str) -> str: + """获取输出文件路径""" + # 更改扩展名为 .pyi (Python stub file) + BaseName = os.path.splitext(RelPath)[0] + OutputRelPath = BaseName + '.pyi' + + # 构建完整输出路径 + if self.config.OutputDir: + OutputPath = os.path.join(self.config.OutputDir, OutputRelPath) + else: + OutputPath = OutputRelPath + + return OutputPath + + def GenerateStub(self, InputFile: str, RelPath: str) -> bool: + """生成单个存根文件""" + try: + self.logger.info(f"Processing: {InputFile}") + + # 确定输出文件路径 + OutputFile = self._GetOutputPath(RelPath) + + # 确保输出目录存在 + OutputDir = os.path.dirname(OutputFile) + if OutputDir and not os.path.exists(OutputDir): + if not self.config.DryRun: + os.makedirs(OutputDir, exist_ok=True) + self.logger.debug(f"Created directory: {OutputDir}") + + if self.config.DryRun: + self.logger.info(f"[DRY RUN] Would generate: {OutputFile}") + return True + + # 根据文件类型选择处理方式 + ext = os.path.splitext(InputFile)[1].lower() + + if ext in ['.h', '.c']: + # C 文件:使用 CHeaderParser + content = self._GenerateFromC(InputFile, RelPath) + elif ext == '.py': + # Python 文件:使用 PythonToStubConverter + content = self._GenerateFromPy(InputFile, RelPath) + else: + self.logger.warning(f"Unsupported file type: {ext}") + return False + + # 写入文件 + with open(OutputFile, 'w', encoding='utf-8') as f: + f.write(content) + + self.GeneratedFiles.append(OutputFile) + self.logger.info(f"Generated: {OutputFile}") + return True + + except Exception as e: + self.logger.error(f"Failed to process {InputFile}: {e}") + import traceback + traceback.print_exc() + self.FailedFiles.append(InputFile) + return False + + def _GenerateFromC(self, InputFile: str, RelPath: str) -> str: + """从 C 文件生成存根""" + parser = CHeaderParser() + parser.parse_file(InputFile) + + generator = PythonStubGenerator(parser) + ModuleName = os.path.splitext(os.path.basename(InputFile))[0] + content = generator.generate(ModuleName) + + # 添加宏守卫(如果需要) + if self.config.GenerateGuards: + guard_name = self._GenerateGuardName(InputFile) + guard_comment = f"\n# Guard: {guard_name}\n" + content = content + guard_comment + + return content + + def _GenerateFromPy(self, InputFile: str, RelPath: str) -> str: + """从 Python 文件生成存根""" + with open(InputFile, 'r', encoding='utf-8') as f: + PyContent = f.read() + + ModuleName = os.path.splitext(os.path.basename(InputFile))[0] + content = PythonToStubConverter.convert(PyContent, ModuleName) + + # 添加宏守卫(如果需要) + if self.config.GenerateGuards: + guard_name = self._GenerateGuardName(InputFile) + guard_comment = f"\n# Guard: {guard_name}\n" + content = content + guard_comment + + return content + + def run(self) -> bool: + """运行生成器""" + self.logger.info("=" * 60) + self.logger.info("StubGen - C/H/Py to Python Stub Generator") + self.logger.info("=" * 60) + + # 查找输入文件 + InputFiles = self.FindInputFiles() + + if not InputFiles: + self.logger.warning("No input files found!") + return False + + self.logger.info(f"Found {len(InputFiles)} input file(s)") + for FilePath, RelPath in InputFiles: + self.logger.debug(f" - {RelPath}") + + # 处理每个文件 + SuccessCount = 0 + for FilePath, RelPath in InputFiles: + if self.GenerateStub(FilePath, RelPath): + SuccessCount += 1 + + # 输出统计信息 + self.logger.info("=" * 60) + self.logger.info(f"Summary: {SuccessCount}/{len(InputFiles)} files generated successfully") + + if self.FailedFiles: + self.logger.warning(f"Failed files ({len(self.FailedFiles)}):") + for f in self.FailedFiles: + self.logger.warning(f" - {f}") + + return SuccessCount == len(InputFiles) + + +def main(): + parser = argparse.ArgumentParser( + description='StubGen - Generate Python stub files from C/H/Py sources', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=''' +Examples: + # 使用配置文件 + %(prog)s -c config.json + + # 处理单个文件 + %(prog)s -i input.h -o output.py + + # 批量处理目录(保持目录结构) + %(prog)s -d ./kernel -o ./kernel/include + + # 干运行(不实际生成文件) + %(prog)s -d ./kernel --dry-run + + # 不生成宏守卫 + %(prog)s -d ./kernel --no-guards + ''' + ) + + # 输入选项 + InputGroup = parser.add_mutually_exclusive_group(required=True) + InputGroup.add_argument('-c', '--config', help='Configuration file (JSON)') + InputGroup.add_argument('-i', '--input', help='Input file') + InputGroup.add_argument('-d', '--directory', help='Input directory') + + # 输出选项 + parser.add_argument('-o', '--output', help='Output directory') + + # 其他选项 + parser.add_argument('--include', action='append', + help='Include patterns (default: *.h, *.c, *.py)') + parser.add_argument('--exclude', action='append', + help='Exclude patterns') + parser.add_argument('--no-guards', action='store_true', + help='Do not generate guard macros') + parser.add_argument('--no-structure', action='store_true', + help='Do not preserve directory structure') + parser.add_argument('-v', '--verbose', action='store_true', + help='Verbose output') + parser.add_argument('--dry-run', action='store_true', + help='Dry run (do not create files)') + + args = parser.parse_args() + + # 加载配置 + if args.config: + if not os.path.exists(args.config): + print(f"Error: Config file not found: {args.config}") + sys.exit(1) + config = StubGenConfig.from_file(args.config) + else: + config = StubGenConfig() + config.IncludePatterns = args.include or ['*.h', '*.c', '*.py'] + config.ExcludePatterns = args.exclude or [] + config.GenerateGuards = not args.no_guards + config.PreserveStructure = not args.no_structure + config.verbose = args.verbose + config.DryRun = args.dry_run + + if args.input: + config.InputFiles = [args.input] + if args.output: + config.OutputDir = os.path.dirname(args.output) or '.' + elif args.directory: + config.InputDir = args.directory + if args.output: + config.OutputDir = args.output + + # 创建生成器并运行 + generator = StubGen(config) + + # 如果指定了单个输出文件,直接处理 + if args.input and args.output and not os.path.isdir(args.output): + RelPath = os.path.relpath(args.input, config.InputDir or '.') + success = generator.GenerateStub(args.input, RelPath) + else: + success = generator.run() + + sys.exit(0 if success else 1) + + +if __name__ == '__main__': + main() diff --git a/lib/StubGen/__init__.py b/lib/StubGen/__init__.py new file mode 100644 index 0000000..00a45bd --- /dev/null +++ b/lib/StubGen/__init__.py @@ -0,0 +1,6 @@ +"""StubGen 包 - 存根文件生成器""" +from lib.StubGen.Config import StubGenConfig +from lib.StubGen.Converter import PythonToStubConverter +from lib.StubGen.Generator import StubGen, main + +__all__ = ['StubGenConfig', 'PythonToStubConverter', 'StubGen', 'main'] diff --git a/lib/core/AsmIntelToAtt.py b/lib/core/AsmIntelToAtt.py deleted file mode 100644 index 7a15058..0000000 --- a/lib/core/AsmIntelToAtt.py +++ /dev/null @@ -1,534 +0,0 @@ -from __future__ import annotations -import re - - -_X86_REGS = { - 'al', 'ah', 'ax', 'eax', 'rax', - 'bl', 'bh', 'bx', 'ebx', 'rbx', - 'cl', 'ch', 'cx', 'ecx', 'rcx', - 'dl', 'dh', 'dx', 'edx', 'rdx', - 'sil', 'si', 'esi', 'rsi', - 'dil', 'di', 'edi', 'rdi', - 'bpl', 'bp', 'ebp', 'rbp', - 'spl', 'sp', 'esp', 'rsp', - 'rip', 'eip', 'ip', - 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', - 'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b', - 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w', - 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d', -} - -_CR_REGS = {'cr0', 'cr2', 'cr3', 'cr4', 'cr8'} -_SEG_REGS = {'ds', 'es', 'fs', 'gs', 'ss', 'cs'} - -_SIZE_MAP = { - 'al': 'b', 'ah': 'b', 'ax': 'w', 'eax': 'l', 'rax': 'q', - 'bl': 'b', 'bh': 'b', 'bx': 'w', 'ebx': 'l', 'rbx': 'q', - 'cl': 'b', 'ch': 'b', 'cx': 'w', 'ecx': 'l', 'rcx': 'q', - 'dl': 'b', 'dh': 'b', 'dx': 'w', 'edx': 'l', 'rdx': 'q', - 'si': 'w', 'esi': 'l', 'rsi': 'q', - 'di': 'w', 'edi': 'l', 'rdi': 'q', - 'bp': 'w', 'ebp': 'l', 'rbp': 'q', - 'sp': 'w', 'esp': 'l', 'rsp': 'q', - 'ip': 'w', 'eip': 'l', 'rip': 'q', - 'r8b': 'b', 'r8w': 'w', 'r8d': 'l', 'r8': 'q', - 'r9b': 'b', 'r9w': 'w', 'r9d': 'l', 'r9': 'q', - 'r10b': 'b', 'r10w': 'w', 'r10d': 'l', 'r10': 'q', - 'r11b': 'b', 'r11w': 'w', 'r11d': 'l', 'r11': 'q', - 'r12b': 'b', 'r12w': 'w', 'r12d': 'l', 'r12': 'q', - 'r13b': 'b', 'r13w': 'w', 'r13d': 'l', 'r13': 'q', - 'r14b': 'b', 'r14w': 'w', 'r14d': 'l', 'r14': 'q', - 'r15b': 'b', 'r15w': 'w', 'r15d': 'l', 'r15': 'q', -} - -_SIZE_PREFIX = { - 'byte': 'b', - 'word': 'w', - 'dword': 'l', - 'qword': 'q', -} - -_TWO_OPS_SWAP = frozenset({ - 'mov', 'lea', 'add', 'sub', 'adc', 'sbb', - 'and', 'or', 'xor', 'cmp', 'test', - 'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'rcl', 'rcr', - 'bt', 'btc', 'btr', 'bts', - 'xadd', 'xchg', 'cmpxchg', -}) - -_NO_SUFFIX_OPS = frozenset({ - 'call', 'jmp', 'ret', 'push', 'pop', - 'cli', 'sti', 'hlt', 'nop', 'cld', 'std', 'cpuid', 'rdmsr', 'wrmsr', - 'sfence', 'mfence', 'lfence', 'fninit', 'pause', 'ud2', - 'invlpg', 'swapgs', 'syscall', 'sysret', 'iretq', 'int', - 'fxsave', 'fxrstor', 'stmxcsr', 'ldmxcsr', - 'bswap', 'cbw', 'cwde', 'cdqe', 'cwd', 'cdq', 'cqo', - 'sete', 'setne', 'seta', 'setae', 'setb', 'setbe', - 'setg', 'setge', 'setl', 'setle', 'sets', 'setns', 'setc', 'setnc', - 'seto', 'setno', 'setp', 'setnp', - 'cmovo', 'cmovno', 'cmovb', 'cmovae', 'cmove', 'cmovne', - 'cmova', 'cmovbe', 'cmovg', 'cmovge', 'cmovl', 'cmovle', - 'cmovs', 'cmovns', 'cmovc', 'cmovnc', 'cmovp', 'cmovnp', -}) - -_BRANCH_OPS = frozenset({ - 'jz', 'jnz', 'je', 'jne', 'jg', 'jl', 'jge', 'jle', - 'ja', 'jb', 'jae', 'jbe', 'jo', 'jno', 'js', 'jns', - 'jc', 'jnc', 'jp', 'jnp', 'loop', 'jcxz', 'jecxz', 'jrcxz', -}) - -_STRING_OPS = frozenset({ - 'lodsb', 'lodsw', 'lodsd', 'lodsq', - 'stosb', 'stosw', 'stosd', 'stosq', - 'movsb', 'movsw', 'movsd', 'movsq', - 'cmpsb', 'cmpsw', 'cmpsd', 'cmpsq', - 'scasb', 'scasw', 'scasd', 'scasq', - 'insb', 'insw', 'insd', 'outsb', 'outsw', 'outsd', -}) - -_STRING_OPS_ATT_MAP = { - 'lodsd': 'lodsl', 'stosd': 'stosl', 'movsd': 'movsl', - 'cmpsd': 'cmpsl', 'scasd': 'scasl', 'insd': 'insl', - 'outsd': 'outsl', -} - -_PREFIX_OPS = frozenset({ - 'rep', 'repe', 'repz', 'repne', 'repnz', 'lock', -}) - - -def _is_operand_ref(token: str) -> bool: - return bool(re.match(r'^\$\d+$', token)) - - -def _parse_operands(operands_str: str): - result = [] - current = '' - depth = 0 - i = 0 - while i < len(operands_str): - ch = operands_str[i] - if ch == '[' or ch == '(': - depth += 1 - current += ch - elif ch == ']' or ch == ')': - depth -= 1 - current += ch - elif ch == ',' and depth == 0: - result.append(current.strip()) - current = '' - else: - current += ch - i += 1 - if current.strip(): - result.append(current.strip()) - return result - - -def _tokenize_mem(mem: str) -> list: - result = [] - current = '' - i = 0 - while i < len(mem): - ch = mem[i] - if ch == '(': - if current.strip(): - result.append(current.strip()) - current = '' - result.append('(') - i += 1 - elif ch == ')': - if current.strip(): - result.append(current.strip()) - current = '' - result.append(')') - i += 1 - elif ch in '+-': - if current.strip(): - result.append(current.strip()) - current = '' - result.append(ch) - i += 1 - elif ch in ' \t': - if current.strip(): - result.append(current.strip()) - current = '' - i += 1 - else: - current += ch - i += 1 - if current.strip(): - result.append(current.strip()) - return result - - -def _convert_mem_token(token: str) -> str: - if token in ('(', ')', '+', '-'): - return token - if _is_operand_ref(token): - return token - if token.lower() in _X86_REGS: - return '%' + token - try: - int(token, 0) - return token - except ValueError: - pass - return token - - -def _convert_mem_operand(op: str) -> str: - op = op.strip().replace('[', '(').replace(']', ')') - - m = re.match(r'^\(([^)]+)\)$', op) - if m: - inner = m.group(1).strip() - return _convert_mem_inner(inner) - - return _convert_mem_inner(op.strip('()')) - - -def _convert_mem_inner(inner: str) -> str: - tokens = [] - current = '' - i = 0 - while i < len(inner): - ch = inner[i] - if ch in ' \t': - if current.strip(): - tokens.append(current.strip()) - current = '' - i += 1 - elif ch in '+-': - if current.strip(): - tokens.append(current.strip()) - current = '' - tokens.append(ch) - i += 1 - else: - current += ch - i += 1 - if current.strip(): - tokens.append(current.strip()) - - base = '' - index = '' - scale = '' - disp = '' - op = '+' - - for tok in tokens: - if tok == '+': - op = '+' - continue - elif tok == '-': - op = '-' - continue - - is_reg = tok.lower() in _X86_REGS or tok.lower() in _CR_REGS - is_operand = _is_operand_ref(tok) - - if is_reg or is_operand: - if not base: - base = _convert_mem_token(tok) - elif not index: - index = _convert_mem_token(tok) - else: - disp += ('+' if op == '+' else '-') + tok - else: - try: - int(tok, 0) - if op == '-': - disp += '-' + tok - else: - disp += tok - except ValueError: - if op == '-': - disp += '-' + tok - else: - if not base: - base = tok - else: - disp += tok - - result = '' - if disp: - result = disp - result += '(' - if base: - result += base - if index: - result += ',' + index - if scale: - result += ',' + scale - result += ')' - return result - - -def _att_convert_operand(op: str) -> str: - op = op.strip() - if not op: - return op - - m = re.match(r'^(byte|word|dword|qword)\s+ptr\s+(.+)$', op, re.IGNORECASE) - if m: - op = m.group(2).strip() - - if '[' in op or ']' in op: - return _convert_mem_operand(op) - - if _is_operand_ref(op): - return op - - if op.lower() in _CR_REGS: - return '%' + op - if op.lower() in _SEG_REGS: - return '%' + op - if op.lower() in _X86_REGS: - return '%' + op - - try: - int(op, 0) - return '$$' + op - except ValueError: - pass - - if op.startswith('~'): - inner = op[1:] - try: - int(inner, 0) - return '$$' + op - except ValueError: - pass - - return op - - -def _extract_size(op: str) -> str: - m = re.match(r'^(byte|word|dword|qword)\s+ptr\s+', op, re.IGNORECASE) - if m: - return _SIZE_PREFIX.get(m.group(1).lower(), '') - - cleaned = op.lower().replace('[', '(').replace(']', ')').replace('$', '') - for reg in _CR_REGS: - if re.search(r'(? str: - for o in operands: - s = _extract_size(o) - if s: - return s - if op in ('imul',): - return 'l' - if op in ('shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'rcl', 'rcr'): - return 'q' - return 'q' - - -def _convert_instruction(op: str, operands: list) -> str: - op_lower = op.lower() - - if op_lower in _PREFIX_OPS and len(operands) == 0: - return op_lower - - if op_lower in _PREFIX_OPS and len(operands) >= 1: - att_ops = [] - for o in operands: - o_lower = o.strip().lower() - if o_lower in _STRING_OPS_ATT_MAP: - att_ops.append(_STRING_OPS_ATT_MAP[o_lower]) - elif o_lower in _NO_SUFFIX_OPS or o_lower in _STRING_OPS: - att_ops.append(o) - else: - att_ops.append(_att_convert_operand(o)) - return f"{op_lower} {' '.join(att_ops)}" - - if op_lower in ('push', 'pop') and len(operands) >= 1: - p = _att_convert_operand(operands[0]) - return f"{op_lower} {p}" - - if op_lower == 'in' and len(operands) >= 2: - dst, port = operands[0], operands[1] - suffix = _size_suffix_for_all([dst], op_lower) or 'b' - return f"in{suffix} {_att_convert_operand(port)}, {_att_convert_operand(dst)}" - - if op_lower == 'out' and len(operands) >= 2: - port, src = operands[0], operands[1] - suffix = _size_suffix_for_all([src], op_lower) or 'b' - return f"out{suffix} {_att_convert_operand(src)}, {_att_convert_operand(port)}" - - if op_lower in ('lidt', 'lgdt', 'sidt', 'sgdt') and len(operands) >= 1: - return f"{op_lower}q {_att_convert_operand(operands[0])}" - - if op_lower == 'call' and len(operands) >= 1: - target = operands[0].strip() - att_target = _att_convert_operand(target) - if _is_operand_ref(target): - return f"call *{att_target}" - if target.startswith('[') or target.startswith('('): - return f"call *{att_target}" - if target.lower() in _X86_REGS or target.lower() in _CR_REGS: - return f"call *{att_target}" - return f"call {att_target}" - - if op_lower == 'jmp' and len(operands) >= 1: - target = operands[0].strip() - att_target = _att_convert_operand(target) - if _is_operand_ref(target): - return f"jmp *{att_target}" - if target.startswith('[') or target.startswith('('): - return f"jmp *{att_target}" - if target.lower() in _X86_REGS or target.lower() in _CR_REGS: - return f"jmp *{att_target}" - return f"jmp {att_target}" - - if op_lower in _BRANCH_OPS and len(operands) >= 1: - target = operands[0].strip() - att_target = _att_convert_operand(target) - return f"{op_lower} {att_target}" - - if op_lower == 'imul' and len(operands) >= 3: - src1, src2, imm = operands[0], operands[1], operands[2] - suffix = _size_suffix_for_all([src1, src2], op_lower) - return f"imul{suffix} {_att_convert_operand(imm)}, {_att_convert_operand(src1)}, {_att_convert_operand(src2)}" - - if op_lower == 'movzx' and len(operands) >= 2: - dst, src = operands[0], operands[1] - src_size = _extract_size(src) or 'b' - dst_size = _extract_size(dst) or 'l' - return f"movz{src_size}{dst_size} {_att_convert_operand(src)}, {_att_convert_operand(dst)}" - - if op_lower == 'movsxd' and len(operands) >= 2: - dst, src = operands[0], operands[1] - src_size = _extract_size(src) or 'l' - dst_size = _extract_size(dst) or 'q' - return f"movs{src_size}{dst_size} {_att_convert_operand(src)}, {_att_convert_operand(dst)}" - - if op_lower in _TWO_OPS_SWAP and len(operands) >= 2: - src, dst = operands[0], operands[1] - suffix = _size_suffix_for_all([src, dst], op_lower) - return f"{op_lower}{suffix} {_att_convert_operand(dst)}, {_att_convert_operand(src)}" - - if op_lower in _NO_SUFFIX_OPS or op_lower in _STRING_OPS or len(operands) == 0: - att_op = _STRING_OPS_ATT_MAP.get(op_lower, op_lower) - parts = [att_op] + [_att_convert_operand(o) for o in operands] - return ' '.join(parts) - - if len(operands) >= 3: - suffix = _size_suffix_for_all(operands, op_lower) - converted_ops = [_att_convert_operand(o) for o in operands] - return f"{op_lower}{suffix} {', '.join(converted_ops[1:])}, {converted_ops[0]}" - - if len(operands) >= 2: - src, dst = operands[0], operands[1] - suffix = _size_suffix_for_all([src, dst], op_lower) - return f"{op_lower}{suffix} {_att_convert_operand(dst)}, {_att_convert_operand(src)}" - - if len(operands) == 1: - suffix = _size_suffix_for_all(operands, op_lower) - return f"{op_lower}{suffix} {_att_convert_operand(operands[0])}" - - return op_lower - - -def _find_comment(s: str) -> int: - in_string = False - i = 0 - while i < len(s): - ch = s[i] - if ch == '"': - in_string = not in_string - elif ch == ';' and not in_string: - return i - i += 1 - return -1 - - -def _convert_single(stmt: str) -> str: - stmt = re.sub(r'%(\d+)', r'$\1', stmt) - - if stmt.strip().startswith('.'): - return stmt - - space_idx = -1 - for i, ch in enumerate(stmt): - if ch in ' \t': - space_idx = i - break - - if space_idx < 0: - op = stmt - operands_str = '' - else: - op = stmt[:space_idx] - operands_str = stmt[space_idx:] - - op = op.strip() - operands_str = operands_str.strip() - - if not operands_str: - if op.lower() in _X86_REGS: - return '%' + op - return op - - operands = _parse_operands(operands_str) - return _convert_instruction(op, operands) - - -def convert(template: str) -> str: - lines = template.split('\n') - result = [] - for line in lines: - stripped = line.strip() - if not stripped: - result.append('') - continue - - stripped = stripped.replace('\t', ' ') - - statements = stripped.split(';') - converted_stmts = [] - for stmt in statements: - stmt = stmt.strip() - if not stmt: - continue - - comment_pos = _find_comment(stmt) - if comment_pos >= 0: - code_part = stmt[:comment_pos].strip() - comment_part = stmt[comment_pos:].strip() - else: - code_part = stmt - comment_part = '' - - if code_part.startswith('.'): - converted_stmts.append(code_part + (f' ; {comment_part}' if comment_part else '')) - continue - - m = re.match(r'^(\d+):(.*)$', code_part) - if m: - label_num = m.group(1) - rest = m.group(2).strip() - if rest: - converted_rest = _convert_single(rest) - converted_stmts.append(f"{label_num}: {converted_rest}" + (f' ; {comment_part}' if comment_part else '')) - else: - converted_stmts.append(f"{label_num}:" + (f' ; {comment_part}' if comment_part else '')) - continue - - converted = _convert_single(code_part) - if comment_part: - converted += f' ; {comment_part}' - converted_stmts.append(converted) - - result.append('; '.join(converted_stmts)) - return '\n'.join(result) diff --git a/lib/core/DecoratorPass.py b/lib/core/DecoratorPass.py index c3e5f07..88b93ff 100644 --- a/lib/core/DecoratorPass.py +++ b/lib/core/DecoratorPass.py @@ -1,522 +1,522 @@ -""" -DecoratorPass - Viper 语言自定义装饰器的 IR 层包装转换 (v4) - -v4 增强版特性: -1. 栈帧局部上下文 (ctx):替代全局变量,解决并发/递归状态错乱 -2. 流程劫持:handler 返回 i32 控制原函数调用次数 - - 返回 0:跳过原函数调用(@cache, @mock) - - 返回 1:正常调用一次(默认) - - 返回 N > 1:循环调用 N 次(@repeat) -3. alwaysinline 属性:消除 wrapper 调用开销 -4. 参数打包与修改:pre-phase 后从 args_struct 读回参数,装饰器可修改入参 -5. 返回值修改:ret_ptr 可写,装饰器可在后置阶段修改返回值 -6. 递归装饰保护:最外层 wrapper 检查全局标志位,递归调用时跳过所有装饰逻辑 - -装饰器调用约定 (v4): - i32 decor_name(i8* ctx, i8* func_name, i32 phase, - i8* args_ptr, i8* ret_ptr, i8* decor_args_ptr) - - 参数说明: - ctx : i8* - 栈帧局部上下文缓冲区(32字节),每次调用独立分配 - 前置阶段可写入状态,后置阶段可读取,生命周期绑定本次调用 - 多线程/递归完全隔离,替代全局变量 - func_name : i8* - 原始函数名字符串 - phase : i32 - 执行阶段(0=前置, 1=后置) - args_ptr : i8* - 指向函数参数打包结构体(可读写,无参数时为 null) - 前置阶段可写入修改参数值,wrapper 会从结构体读回修改后的参数 - ret_ptr : i8* - 指向返回值(前置阶段为 null,void 函数始终为 null) - 后置阶段可读写,装饰器可修改返回值 - decor_args_ptr : i8* - 指向装饰器参数打包结构体(无参数装饰器为 null) - - 返回值(仅前置阶段有效,后置阶段忽略): - 0 : 跳过原函数调用(@cache, @mock, @skip) - 1 : 调用原函数一次(默认行为,@log, @timing, @trace) - N>1: 循环调用原函数 N 次(@repeat, @benchmark) - - 编译器生成的 wrapper(以 add(i32, i32) -> i32, @log 为例): - define i32 @__decor_wrap_add(i32 %a, i32 %b) alwaysinline { - entry: - ; 递归保护:检查标志位 - %rec_val = load i8, i8* @__decor_rec___decor_wrap_add - %is_rec = icmp ne i8 %rec_val, 0 - br i1 %is_rec, label %recursive_call, label %decorated_entry - - recursive_call: - ; 递归调用:跳过所有装饰逻辑,直接调用原函数 - %rec_result = call i32 @add(i32 %a, i32 %b) - ret i32 %rec_result - - decorated_entry: - ; 设置递归保护标志 - store i8 1, i8* @__decor_rec___decor_wrap_add - - ; 分配栈帧局部上下文 - %ctx = alloca [32 x i8] - %ctx_ptr = bitcast [32 x i8]* %ctx to i8* - - ; 打包函数参数到结构体(装饰器可通过 args_ptr 修改) - %args = alloca {i32, i32} - store i32 %a, i32* getelementptr({i32, i32}* %args, i32 0, i32 0) - store i32 %b, i32* getelementptr({i32, i32}* %args, i32 0, i32 1) - %args_ptr = bitcast {i32, i32}* %args to i8* - - ; 分配返回值存储(零初始化) - %ret = alloca i32 - store i32 0, i32* %ret - - ; 前置阶段:handler 返回调用次数 - %n = call i32 @log(i8* %ctx_ptr, i8* "add", i32 0, - i8* %args_ptr, i8* null, i8* null) - br label %loop.header - - loop.header: - %i = phi i32 [0, %decorated_entry], [%i.next, %loop.body] - %cond = icmp slt i32 %i, %n - br i1 %cond, label %loop.body, label %post - - loop.body: - ; 从结构体读回参数(装饰器可能已修改) - %a.loaded = load i32, i32* getelementptr({i32, i32}* %args, i32 0, i32 0) - %b.loaded = load i32, i32* getelementptr({i32, i32}* %args, i32 0, i32 1) - %result = call i32 @add(i32 %a.loaded, i32 %b.loaded) - store i32 %result, i32* %ret - %i.next = add i32 %i, 1 - br label %loop.header - - post: - %ret_ptr = bitcast i32* %ret to i8* - call i32 @log(i8* %ctx_ptr, i8* "add", i32 1, - i8* %args_ptr, i8* %ret_ptr, i8* null) - - ; 清除递归保护标志 - store i8 0, i8* @__decor_rec___decor_wrap_add - - %final = load i32, i32* %ret - ret i32 %final - } - -链式装饰器(从下到上嵌套): - @log - @timing - def f(x) -> int: - 等价于 log(timing(f)) - 执行顺序:log_pre → timing_pre → f → timing_post → log_post - 生成:__decor_wrap_f (log) → __decor_wrap_f_timing (timing) → f - 递归保护仅在最外层 wrapper 生效,递归调用直接跳到原始 f -""" -from __future__ import annotations -import llvmlite.ir as ir - - -# 栈帧局部上下文缓冲区大小(字节) -_CTX_SIZE = 32 - -# 装饰器处理函数的 LLVM 签名:i32 (i8*, i8*, i32, i8*, i8*, i8*) -_DECOR_HANDLER_PARAM_TYPES = None # 延迟初始化 - - -def _get_decor_handler_func_type(): - """获取装饰器处理函数的 LLVM FunctionType: i32 (i8*, i8*, i32, i8*, i8*, i8*)""" - global _DECOR_HANDLER_PARAM_TYPES - if _DECOR_HANDLER_PARAM_TYPES is None: - i8_ptr = ir.IntType(8).as_pointer() - _DECOR_HANDLER_PARAM_TYPES = ir.FunctionType( - ir.IntType(32), - [i8_ptr, i8_ptr, ir.IntType(32), i8_ptr, i8_ptr, i8_ptr] - ) - return _DECOR_HANDLER_PARAM_TYPES - - -def _find_or_declare_handler(module, handler_name): - """在 module 中查找或声明装饰器处理函数""" - for f in module.functions: - if f.name == handler_name: - return f - func_type = _get_decor_handler_func_type() - handler = ir.Function(module, func_type, name=handler_name) - return handler - - -def _make_string_constant(module, text, name_prefix="decor.str"): - """在 module 中创建一个全局字符串常量,返回 i8* 指针""" - counter = getattr(_make_string_constant, '_counter', 0) + 1 - _make_string_constant._counter = counter - const_name = f"{name_prefix}.{counter}" - - encoded = text.encode('utf-8') + b'\x00' - const_type = ir.ArrayType(ir.IntType(8), len(encoded)) - const_val = ir.Constant(const_type, bytearray(encoded)) - - global_var = ir.GlobalVariable(module, const_type, name=const_name) - global_var.global_constant = True - global_var.linkage = 'private' - global_var.initializer = const_val - - return global_var.bitcast(ir.IntType(8).as_pointer()) - - -def _make_decor_args_constant(module, decorator_info): - """ - 为带参数的装饰器生成全局常量结构体,返回 i8* 指针。 - 无参数装饰器返回 null。 - - 支持的参数类型: - - int → i32 / i64 - - float → f64 - - bool → i1 - - str → i8*(全局字符串常量) - """ - deco_args = decorator_info.get('args', []) - deco_kwargs = decorator_info.get('kwargs', {}) - - if not deco_args and not deco_kwargs: - return ir.Constant(ir.IntType(8).as_pointer(), None) - - field_types = [] - field_values = [] - - for arg in deco_args: - llvm_type, llvm_val = _python_value_to_llvm(module, arg) - if llvm_type is None: - return ir.Constant(ir.IntType(8).as_pointer(), None) - field_types.append(llvm_type) - field_values.append(llvm_val) - - for kw in sorted(deco_kwargs.keys()): - llvm_type, llvm_val = _python_value_to_llvm(module, deco_kwargs[kw]) - if llvm_type is None: - return ir.Constant(ir.IntType(8).as_pointer(), None) - field_types.append(llvm_type) - field_values.append(llvm_val) - - struct_type = ir.LiteralStructType(field_types) - struct_const = ir.Constant(struct_type, field_values) - - counter = getattr(_make_decor_args_constant, '_counter', 0) + 1 - _make_decor_args_constant._counter = counter - global_name = f"__decor_args.{counter}" - - global_var = ir.GlobalVariable(module, struct_type, name=global_name) - global_var.global_constant = True - global_var.linkage = 'private' - global_var.initializer = struct_const - - return global_var.bitcast(ir.IntType(8).as_pointer()) - - -def _python_value_to_llvm(module, value): - """将 Python 值转换为 (LLVM类型, LLVM常量) 元组。""" - if isinstance(value, bool): - return ir.IntType(1), ir.Constant(ir.IntType(1), int(value)) - elif isinstance(value, int): - if -2**31 <= value < 2**31: - return ir.IntType(32), ir.Constant(ir.IntType(32), value) - else: - return ir.IntType(64), ir.Constant(ir.IntType(64), value) - elif isinstance(value, float): - return ir.DoubleType(), ir.Constant(ir.DoubleType(), value) - elif isinstance(value, str): - str_const = _make_string_constant(module, value, name_prefix="decor.arg") - return ir.IntType(8).as_pointer(), str_const - else: - return None, None - - -def _zero_constant(llvm_type): - """为给定 LLVM 类型创建零值常量""" - if isinstance(llvm_type, ir.IntType): - return ir.Constant(llvm_type, 0) - elif isinstance(llvm_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(llvm_type, 0.0) - elif isinstance(llvm_type, ir.PointerType): - return ir.Constant(llvm_type, None) - elif isinstance(llvm_type, ir.ArrayType): - elem_zero = _zero_constant(llvm_type.element) - if elem_zero is None: - return None - return ir.Constant(llvm_type, [elem_zero] * llvm_type.count) - else: - return None - - -def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, - decorator_info, is_export=False, - is_outermost=False, true_original_func=None): - """ - 为单个装饰器生成一层 wrapper 函数。 - - v4 Wrapper 结构(最外层含递归保护): - entry → 递归保护检查(仅最外层) - recursive_call → 递归时直接调用原函数,跳过所有装饰(仅最外层) - decorated_entry → 设置递归标志,分配 ctx/args/ret,调用 handler 前置 - loop.header → phi 计数器,比较 i < n_calls - loop.body → 从 args_struct 读回参数(支持修改),调用原函数 - post → 调用 handler 后置,清除递归标志,返回结果 - """ - decor_name = decorator_info['name'] - handler = _find_or_declare_handler(module, decor_name) - func_name_const = _make_string_constant(module, func_name_str, name_prefix="decor.fn") - - func_type = original_func.ftype - return_type = func_type.return_type - param_types = [p.type for p in original_func.args] - is_void = isinstance(return_type, ir.VoidType) - - wrapper_type = ir.FunctionType(return_type, param_types) - wrapper = ir.Function(module, wrapper_type, name=wrapper_name) - - # 添加 alwaysinline 属性,优化器完全内联消除调用开销 - wrapper.attributes.add('alwaysinline') - - i32 = ir.IntType(32) - i8 = ir.IntType(8) - i8_ptr = ir.IntType(8).as_pointer() - phase_pre = ir.Constant(i32, 0) - phase_post = ir.Constant(i32, 1) - null_ptr = ir.Constant(i8_ptr, None) - zero_i32 = ir.Constant(i32, 0) - one_i32 = ir.Constant(i32, 1) - one_i8 = ir.Constant(i8, 1) - zero_i8 = ir.Constant(i8, 0) - - # 递归保护:仅最外层 wrapper 生成 - rec_flag = None - if is_outermost and true_original_func is not None: - rec_flag_name = f"__decor_rec_{wrapper_name}" - # 检查是否已存在 - rec_flag = None - for g in module.global_values: - if g.name == rec_flag_name: - rec_flag = g - break - if rec_flag is None: - rec_flag = ir.GlobalVariable(module, i8, name=rec_flag_name) - rec_flag.global_constant = False - rec_flag.linkage = 'internal' - rec_flag.initializer = zero_i8 - - # 创建基本块 - entry_block = wrapper.append_basic_block("entry") - - if rec_flag is not None: - recursive_call_block = wrapper.append_basic_block("recursive_call") - decorated_entry_block = wrapper.append_basic_block("decorated_entry") - else: - recursive_call_block = None - decorated_entry_block = None - - loop_header_block = wrapper.append_basic_block("loop.header") - loop_body_block = wrapper.append_basic_block("loop.body") - post_block = wrapper.append_basic_block("post") - - # ==== Entry block ==== - builder = ir.IRBuilder(entry_block) - - if rec_flag is not None: - # 递归保护:检查标志位 - rec_val = builder.load(rec_flag, name="rec_val") - is_recursive = builder.icmp_signed('!=', rec_val, zero_i8) - builder.cbranch(is_recursive, recursive_call_block, decorated_entry_block) - - # ==== Recursive call block ==== - builder = ir.IRBuilder(recursive_call_block) - # 递归调用:直接调用真正的原函数,跳过所有装饰逻辑 - rec_call_args = [arg for arg in wrapper.args] - rec_ret_val = builder.call(true_original_func, rec_call_args) - if is_void: - builder.ret_void() - else: - builder.ret(rec_ret_val) - - # ==== Decorated entry block ==== - builder = ir.IRBuilder(decorated_entry_block) - # 设置递归保护标志 - builder.store(one_i8, rec_flag) - - # 记录 loop.header 的前置块为 decorated_entry_block - loop_predecessor = decorated_entry_block - else: - loop_predecessor = entry_block - - # 1. 分配栈帧局部上下文(每次调用独立,线程安全,递归安全) - ctx_type = ir.ArrayType(ir.IntType(8), _CTX_SIZE) - ctx_alloca = builder.alloca(ctx_type, name="ctx") - ctx_ptr = builder.bitcast(ctx_alloca, i8_ptr) - - # 2. 打包函数参数到结构体(装饰器可通过 args_ptr 读写修改) - args_alloca = None - args_struct_type = None - if param_types: - args_struct_type = ir.LiteralStructType(param_types) - args_alloca = builder.alloca(args_struct_type, name="args") - zero = ir.Constant(i32, 0) - for i, arg in enumerate(wrapper.args): - field_idx = ir.Constant(i32, i) - gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) - builder.store(arg, gep) - args_ptr = builder.bitcast(args_alloca, i8_ptr) - else: - args_ptr = null_ptr - - # 3. 分配返回值存储(零初始化,确保跳过原函数时返回安全默认值) - if not is_void: - ret_alloca = builder.alloca(return_type, name="ret") - zero_val = _zero_constant(return_type) - if zero_val is not None: - builder.store(zero_val, ret_alloca) - else: - ret_alloca = None - - # 4. 获取装饰器参数指针 - decor_args_ptr = _make_decor_args_constant(module, decorator_info) - - # 5. 前置阶段:handler 返回调用次数 - n_calls = builder.call(handler, [ctx_ptr, func_name_const, phase_pre, - args_ptr, null_ptr, decor_args_ptr]) - - # 6. 跳转到循环头 - builder.branch(loop_header_block) - - # ==== Loop header block ==== - builder = ir.IRBuilder(loop_header_block) - i_phi = builder.phi(i32, "i") - i_phi.add_incoming(zero_i32, loop_predecessor) - cond = builder.icmp_signed('<', i_phi, n_calls) - builder.cbranch(cond, loop_body_block, post_block) - - # ==== Loop body block ==== - builder = ir.IRBuilder(loop_body_block) - - # v4: 从 args_struct 读回参数(装饰器可能在 pre-phase 中修改了参数) - if args_alloca is not None and args_struct_type is not None: - zero = ir.Constant(i32, 0) - call_args = [] - for i in range(len(param_types)): - field_idx = ir.Constant(i32, i) - gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) - loaded_arg = builder.load(gep, name=f"arg.{i}") - call_args.append(loaded_arg) - else: - call_args = [] - - ret_val = builder.call(original_func, call_args) - if ret_alloca is not None: - builder.store(ret_val, ret_alloca) - i_next = builder.add(i_phi, one_i32) - i_phi.add_incoming(i_next, loop_body_block) - builder.branch(loop_header_block) - - # ==== Post block ==== - builder = ir.IRBuilder(post_block) - - # 后置阶段 - if ret_alloca is not None: - ret_ptr = builder.bitcast(ret_alloca, i8_ptr) - else: - ret_ptr = null_ptr - builder.call(handler, [ctx_ptr, func_name_const, phase_post, - args_ptr, ret_ptr, decor_args_ptr]) - - # 递归保护:清除标志(必须在 post-phase 之后、return 之前) - if rec_flag is not None: - builder.store(zero_i8, rec_flag) - - # 返回 - if is_void: - builder.ret_void() - else: - final_ret = builder.load(ret_alloca, name="final_ret") - builder.ret(final_ret) - - return wrapper - - -def _redirect_calls(module, old_func, new_func, skip_func_names=None): - """ - 替换 module 中所有对 old_func 的调用指令为对 new_func 的调用。 - 跳过 skip_func_names 中的函数(wrapper 函数内部不应被重定向)。 - """ - if skip_func_names is None: - skip_func_names = set() - - for func in module.functions: - if func.name in skip_func_names: - continue - if func.name == new_func.name: - continue - for block in func.blocks: - for instr in list(block.instructions): - if not isinstance(instr, ir.CallInstr): - continue - callee = instr.callee - if isinstance(callee, ir.Function) and callee is old_func: - instr.callee = new_func - - -def run(Gen): - """ - 执行 DecoratorPass。 - - 处理流程: - 1. 遍历 _decorated_funcs 中所有带装饰标记的函数 - 2. 对每个函数,按装饰器列表从底到顶生成嵌套 wrapper - 3. 将原函数改为 internal 链接 - 4. 替换所有调用点 - """ - if not hasattr(Gen, '_decorated_funcs') or not Gen._decorated_funcs: - return - - module = Gen.module - decorated = Gen._decorated_funcs.copy() - - for mangled_name, info in decorated.items(): - decorators = info['decorators'] - func_name = info['func_name'] - is_export = info['is_export'] - - # 查找原始函数 - original_func = None - for f in module.functions: - if f.name == mangled_name: - original_func = f - break - if original_func is None: - continue - - # 原函数改为 internal 链接(仅 wrapper 调用) - original_func.linkage = 'internal' - - # 按装饰器列表从底到顶生成嵌套 wrapper - # Python 装饰器顺序:@a @b def f() => a(b(f)) - # 执行顺序:先应用最靠近函数的 @b,再应用 @a - - current_func = original_func - all_wrapper_names = set() - - for i in range(len(decorators) - 1, -1, -1): - deco = decorators[i] - is_outermost = (i == 0) - deco_name = deco['name'] - - if is_outermost: - wrapper_name = f"__decor_wrap_{mangled_name}" - else: - wrapper_name = f"__decor_wrap_{mangled_name}_{deco_name}" - - all_wrapper_names.add(wrapper_name) - - wrapper = _generate_single_wrapper( - module, current_func, wrapper_name, - func_name, deco, is_export=is_export, - is_outermost=is_outermost, - true_original_func=original_func if is_outermost else None - ) - current_func = wrapper - - # 更新 functions 映射,使原函数名指向最外层 wrapper - Gen.functions[mangled_name] = current_func - if func_name in Gen.functions: - Gen.functions[func_name] = current_func - - # 替换所有非 wrapper 函数中对原函数的调用 - _redirect_calls(module, original_func, current_func, all_wrapper_names) +""" +DecoratorPass - Viper 语言自定义装饰器的 IR 层包装转换 (v4) + +v4 增强版特性: +1. 栈帧局部上下文 (ctx):替代全局变量,解决并发/递归状态错乱 +2. 流程劫持:handler 返回 i32 控制原函数调用次数 + - 返回 0:跳过原函数调用(@cache, @mock) + - 返回 1:正常调用一次(默认) + - 返回 N > 1:循环调用 N 次(@repeat) +3. alwaysinline 属性:消除 wrapper 调用开销 +4. 参数打包与修改:pre-phase 后从 args_struct 读回参数,装饰器可修改入参 +5. 返回值修改:ret_ptr 可写,装饰器可在后置阶段修改返回值 +6. 递归装饰保护:最外层 wrapper 检查全局标志位,递归调用时跳过所有装饰逻辑 + +装饰器调用约定 (v4): + i32 decor_name(i8* ctx, i8* func_name, i32 phase, + i8* args_ptr, i8* ret_ptr, i8* decor_args_ptr) + + 参数说明: + ctx : i8* - 栈帧局部上下文缓冲区(32字节),每次调用独立分配 + 前置阶段可写入状态,后置阶段可读取,生命周期绑定本次调用 + 多线程/递归完全隔离,替代全局变量 + func_name : i8* - 原始函数名字符串 + phase : i32 - 执行阶段(0=前置, 1=后置) + args_ptr : i8* - 指向函数参数打包结构体(可读写,无参数时为 null) + 前置阶段可写入修改参数值,wrapper 会从结构体读回修改后的参数 + ret_ptr : i8* - 指向返回值(前置阶段为 null,void 函数始终为 null) + 后置阶段可读写,装饰器可修改返回值 + decor_args_ptr : i8* - 指向装饰器参数打包结构体(无参数装饰器为 null) + + 返回值(仅前置阶段有效,后置阶段忽略): + 0 : 跳过原函数调用(@cache, @mock, @skip) + 1 : 调用原函数一次(默认行为,@log, @timing, @trace) + N>1: 循环调用原函数 N 次(@repeat, @benchmark) + + 编译器生成的 wrapper(以 add(i32, i32) -> i32, @log 为例): + define i32 @__decor_wrap_add(i32 %a, i32 %b) alwaysinline { + entry: + ; 递归保护:检查标志位 + %rec_val = Load i8, i8* @__decor_rec___decor_wrap_add + %is_rec = icmp ne i8 %rec_val, 0 + br i1 %is_rec, label %recursive_call, label %decorated_entry + + recursive_call: + ; 递归调用:跳过所有装饰逻辑,直接调用原函数 + %rec_result = call i32 @add(i32 %a, i32 %b) + ret i32 %rec_result + + decorated_entry: + ; 设置递归保护标志 + store i8 1, i8* @__decor_rec___decor_wrap_add + + ; 分配栈帧局部上下文 + %ctx = alloca [32 x i8] + %ctx_ptr = bitcast [32 x i8]* %ctx to i8* + + ; 打包函数参数到结构体(装饰器可通过 args_ptr 修改) + %args = alloca {i32, i32} + store i32 %a, i32* getelementptr({i32, i32}* %args, i32 0, i32 0) + store i32 %b, i32* getelementptr({i32, i32}* %args, i32 0, i32 1) + %args_ptr = bitcast {i32, i32}* %args to i8* + + ; 分配返回值存储(零初始化) + %ret = alloca i32 + store i32 0, i32* %ret + + ; 前置阶段:handler 返回调用次数 + %n = call i32 @log(i8* %ctx_ptr, i8* "add", i32 0, + i8* %args_ptr, i8* null, i8* null) + br label %loop.header + + loop.header: + %i = phi i32 [0, %decorated_entry], [%i.next, %loop.body] + %cond = icmp slt i32 %i, %n + br i1 %cond, label %loop.body, label %post + + loop.body: + ; 从结构体读回参数(装饰器可能已修改) + %a.Loaded = Load i32, i32* getelementptr({i32, i32}* %args, i32 0, i32 0) + %b.Loaded = Load i32, i32* getelementptr({i32, i32}* %args, i32 0, i32 1) + %result = call i32 @add(i32 %a.Loaded, i32 %b.Loaded) + store i32 %result, i32* %ret + %i.next = add i32 %i, 1 + br label %loop.header + + post: + %ret_ptr = bitcast i32* %ret to i8* + call i32 @log(i8* %ctx_ptr, i8* "add", i32 1, + i8* %args_ptr, i8* %ret_ptr, i8* null) + + ; 清除递归保护标志 + store i8 0, i8* @__decor_rec___decor_wrap_add + + %final = Load i32, i32* %ret + ret i32 %final + } + +链式装饰器(从下到上嵌套): + @log + @timing + def f(x) -> int: + 等价于 log(timing(f)) + 执行顺序:log_pre → timing_pre → f → timing_post → log_post + 生成:__decor_wrap_f (log) → __decor_wrap_f_timing (timing) → f + 递归保护仅在最外层 wrapper 生效,递归调用直接跳到原始 f +""" +from __future__ import annotations +import llvmlite.ir as ir + + +# 栈帧局部上下文缓冲区大小(字节) +_CTX_SIZE = 32 + +# 装饰器处理函数的 LLVM 签名:i32 (i8*, i8*, i32, i8*, i8*, i8*) +_DECOR_HANDLER_PARAM_TYPES = None # 延迟初始化 + + +def _get_decor_handler_func_type(): + """获取装饰器处理函数的 LLVM FunctionType: i32 (i8*, i8*, i32, i8*, i8*, i8*)""" + global _DECOR_HANDLER_PARAM_TYPES + if _DECOR_HANDLER_PARAM_TYPES is None: + i8_ptr = ir.IntType(8).as_pointer() + _DECOR_HANDLER_PARAM_TYPES = ir.FunctionType( + ir.IntType(32), + [i8_ptr, i8_ptr, ir.IntType(32), i8_ptr, i8_ptr, i8_ptr] + ) + return _DECOR_HANDLER_PARAM_TYPES + + +def _find_or_declare_handler(module, handler_name): + """在 module 中查找或声明装饰器处理函数""" + for f in module.functions: + if f.name == handler_name: + return f + func_type = _get_decor_handler_func_type() + handler = ir.Function(module, func_type, name=handler_name) + return handler + + +def _make_string_constant(module, text, name_prefix="decor.str"): + """在 module 中创建一个全局字符串常量,返回 i8* 指针""" + counter = getattr(_make_string_constant, '_counter', 0) + 1 + _make_string_constant._counter = counter + const_name = f"{name_prefix}.{counter}" + + encoded = text.encode('utf-8') + b'\x00' + const_type = ir.ArrayType(ir.IntType(8), len(encoded)) + const_val = ir.Constant(const_type, bytearray(encoded)) + + global_var = ir.GlobalVariable(module, const_type, name=const_name) + global_var.global_constant = True + global_var.linkage = 'private' + global_var.initializer = const_val + + return global_var.bitcast(ir.IntType(8).as_pointer()) + + +def _make_decor_args_constant(module, decorator_info): + """ + 为带参数的装饰器生成全局常量结构体,返回 i8* 指针。 + 无参数装饰器返回 null。 + + 支持的参数类型: + - int → i32 / i64 + - float → f64 + - bool → i1 + - str → i8*(全局字符串常量) + """ + deco_args = decorator_info.get('args', []) + deco_kwargs = decorator_info.get('kwargs', {}) + + if not deco_args and not deco_kwargs: + return ir.Constant(ir.IntType(8).as_pointer(), None) + + field_types = [] + field_values = [] + + for arg in deco_args: + llvm_type, llvm_val = _python_value_to_llvm(module, arg) + if llvm_type is None: + return ir.Constant(ir.IntType(8).as_pointer(), None) + field_types.append(llvm_type) + field_values.append(llvm_val) + + for kw in sorted(deco_kwargs.keys()): + llvm_type, llvm_val = _python_value_to_llvm(module, deco_kwargs[kw]) + if llvm_type is None: + return ir.Constant(ir.IntType(8).as_pointer(), None) + field_types.append(llvm_type) + field_values.append(llvm_val) + + struct_type = ir.LiteralStructType(field_types) + struct_const = ir.Constant(struct_type, field_values) + + counter = getattr(_make_decor_args_constant, '_counter', 0) + 1 + _make_decor_args_constant._counter = counter + global_name = f"__decor_args.{counter}" + + global_var = ir.GlobalVariable(module, struct_type, name=global_name) + global_var.global_constant = True + global_var.linkage = 'private' + global_var.initializer = struct_const + + return global_var.bitcast(ir.IntType(8).as_pointer()) + + +def _python_value_to_llvm(module, value): + """将 Python 值转换为 (LLVM类型, LLVM常量) 元组。""" + if isinstance(value, bool): + return ir.IntType(1), ir.Constant(ir.IntType(1), int(value)) + elif isinstance(value, int): + if -2**31 <= value < 2**31: + return ir.IntType(32), ir.Constant(ir.IntType(32), value) + else: + return ir.IntType(64), ir.Constant(ir.IntType(64), value) + elif isinstance(value, float): + return ir.DoubleType(), ir.Constant(ir.DoubleType(), value) + elif isinstance(value, str): + str_const = _make_string_constant(module, value, name_prefix="decor.arg") + return ir.IntType(8).as_pointer(), str_const + else: + return None, None + + +def _ZeroConstant(llvm_type): + """为给定 LLVM 类型创建零值常量""" + if isinstance(llvm_type, ir.IntType): + return ir.Constant(llvm_type, 0) + elif isinstance(llvm_type, (ir.FloatType, ir.DoubleType)): + return ir.Constant(llvm_type, 0.0) + elif isinstance(llvm_type, ir.PointerType): + return ir.Constant(llvm_type, None) + elif isinstance(llvm_type, ir.ArrayType): + elem_zero = _ZeroConstant(llvm_type.element) + if elem_zero is None: + return None + return ir.Constant(llvm_type, [elem_zero] * llvm_type.count) + else: + return None + + +def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, + decorator_info, is_export=False, + is_outermost=False, true_original_func=None): + """ + 为单个装饰器生成一层 wrapper 函数。 + + v4 Wrapper 结构(最外层含递归保护): + entry → 递归保护检查(仅最外层) + recursive_call → 递归时直接调用原函数,跳过所有装饰(仅最外层) + decorated_entry → 设置递归标志,分配 ctx/args/ret,调用 handler 前置 + loop.header → phi 计数器,比较 i < n_calls + loop.body → 从 args_struct 读回参数(支持修改),调用原函数 + post → 调用 handler 后置,清除递归标志,返回结果 + """ + decor_name = decorator_info['name'] + handler = _find_or_declare_handler(module, decor_name) + func_name_const = _make_string_constant(module, func_name_str, name_prefix="decor.fn") + + func_type = original_func.ftype + return_type = func_type.return_type + param_types = [p.type for p in original_func.args] + is_void = isinstance(return_type, ir.VoidType) + + wrapper_type = ir.FunctionType(return_type, param_types) + wrapper = ir.Function(module, wrapper_type, name=wrapper_name) + + # 添加 alwaysinline 属性,优化器完全内联消除调用开销 + wrapper.attributes.add('alwaysinline') + + i32 = ir.IntType(32) + i8 = ir.IntType(8) + i8_ptr = ir.IntType(8).as_pointer() + phase_pre = ir.Constant(i32, 0) + phase_post = ir.Constant(i32, 1) + null_ptr = ir.Constant(i8_ptr, None) + zero_i32 = ir.Constant(i32, 0) + one_i32 = ir.Constant(i32, 1) + one_i8 = ir.Constant(i8, 1) + zero_i8 = ir.Constant(i8, 0) + + # 递归保护:仅最外层 wrapper 生成 + rec_flag = None + if is_outermost and true_original_func is not None: + rec_flag_name = f"__decor_rec_{wrapper_name}" + # 检查是否已存在 + rec_flag = None + for g in module.global_values: + if g.name == rec_flag_name: + rec_flag = g + break + if rec_flag is None: + rec_flag = ir.GlobalVariable(module, i8, name=rec_flag_name) + rec_flag.global_constant = False + rec_flag.linkage = 'internal' + rec_flag.initializer = zero_i8 + + # 创建基本块 + entry_block = wrapper.append_basic_block("entry") + + if rec_flag is not None: + recursive_call_block = wrapper.append_basic_block("recursive_call") + decorated_entry_block = wrapper.append_basic_block("decorated_entry") + else: + recursive_call_block = None + decorated_entry_block = None + + loop_header_block = wrapper.append_basic_block("loop.header") + loop_body_block = wrapper.append_basic_block("loop.body") + post_block = wrapper.append_basic_block("post") + + # ==== Entry block ==== + builder = ir.IRBuilder(entry_block) + + if rec_flag is not None: + # 递归保护:检查标志位 + rec_val = builder.load(rec_flag, name="rec_val") + is_recursive = builder.icmp_signed('!=', rec_val, zero_i8) + builder.cbranch(is_recursive, recursive_call_block, decorated_entry_block) + + # ==== Recursive call block ==== + builder = ir.IRBuilder(recursive_call_block) + # 递归调用:直接调用真正的原函数,跳过所有装饰逻辑 + rec_call_args = [arg for arg in wrapper.args] + rec_ret_val = builder.call(true_original_func, rec_call_args) + if is_void: + builder.ret_void() + else: + builder.ret(rec_ret_val) + + # ==== Decorated entry block ==== + builder = ir.IRBuilder(decorated_entry_block) + # 设置递归保护标志 + builder.store(one_i8, rec_flag) + + # 记录 loop.header 的前置块为 decorated_entry_block + loop_predecessor = decorated_entry_block + else: + loop_predecessor = entry_block + + # 1. 分配栈帧局部上下文(每次调用独立,线程安全,递归安全) + ctx_type = ir.ArrayType(ir.IntType(8), _CTX_SIZE) + ctx_alloca = builder.alloca(ctx_type, name="ctx") + ctx_ptr = builder.bitcast(ctx_alloca, i8_ptr) + + # 2. 打包函数参数到结构体(装饰器可通过 args_ptr 读写修改) + args_alloca = None + args_struct_type = None + if param_types: + args_struct_type = ir.LiteralStructType(param_types) + args_alloca = builder.alloca(args_struct_type, name="args") + zero = ir.Constant(i32, 0) + for i, arg in enumerate(wrapper.args): + field_idx = ir.Constant(i32, i) + gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) + builder.store(arg, gep) + args_ptr = builder.bitcast(args_alloca, i8_ptr) + else: + args_ptr = null_ptr + + # 3. 分配返回值存储(零初始化,确保跳过原函数时返回安全默认值) + if not is_void: + ret_alloca = builder.alloca(return_type, name="ret") + zero_val = _ZeroConstant(return_type) + if zero_val is not None: + builder.store(zero_val, ret_alloca) + else: + ret_alloca = None + + # 4. 获取装饰器参数指针 + decor_args_ptr = _make_decor_args_constant(module, decorator_info) + + # 5. 前置阶段:handler 返回调用次数 + n_calls = builder.call(handler, [ctx_ptr, func_name_const, phase_pre, + args_ptr, null_ptr, decor_args_ptr]) + + # 6. 跳转到循环头 + builder.branch(loop_header_block) + + # ==== Loop header block ==== + builder = ir.IRBuilder(loop_header_block) + i_phi = builder.phi(i32, "i") + i_phi.add_incoming(zero_i32, loop_predecessor) + cond = builder.icmp_signed('<', i_phi, n_calls) + builder.cbranch(cond, loop_body_block, post_block) + + # ==== Loop body block ==== + builder = ir.IRBuilder(loop_body_block) + + # v4: 从 args_struct 读回参数(装饰器可能在 pre-phase 中修改了参数) + if args_alloca is not None and args_struct_type is not None: + zero = ir.Constant(i32, 0) + call_args = [] + for i in range(len(param_types)): + field_idx = ir.Constant(i32, i) + gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) + Loaded_arg = builder.load(gep, name=f"arg.{i}") + call_args.append(Loaded_arg) + else: + call_args = [] + + ret_val = builder.call(original_func, call_args) + if ret_alloca is not None: + builder.store(ret_val, ret_alloca) + i_next = builder.add(i_phi, one_i32) + i_phi.add_incoming(i_next, loop_body_block) + builder.branch(loop_header_block) + + # ==== Post block ==== + builder = ir.IRBuilder(post_block) + + # 后置阶段 + if ret_alloca is not None: + ret_ptr = builder.bitcast(ret_alloca, i8_ptr) + else: + ret_ptr = null_ptr + builder.call(handler, [ctx_ptr, func_name_const, phase_post, + args_ptr, ret_ptr, decor_args_ptr]) + + # 递归保护:清除标志(必须在 post-phase 之后、return 之前) + if rec_flag is not None: + builder.store(zero_i8, rec_flag) + + # 返回 + if is_void: + builder.ret_void() + else: + final_ret = builder.load(ret_alloca, name="final_ret") + builder.ret(final_ret) + + return wrapper + + +def _redirect_calls(module, old_func, new_func, skip_func_names=None): + """ + 替换 module 中所有对 old_func 的调用指令为对 new_func 的调用。 + 跳过 skip_func_names 中的函数(wrapper 函数内部不应被重定向)。 + """ + if skip_func_names is None: + skip_func_names = set() + + for func in module.functions: + if func.name in skip_func_names: + continue + if func.name == new_func.name: + continue + for block in func.blocks: + for instr in list(block.instructions): + if not isinstance(instr, ir.CallInstr): + continue + callee = instr.callee + if isinstance(callee, ir.Function) and callee is old_func: + instr.callee = new_func + + +def run(Gen): + """ + 执行 DecoratorPass。 + + 处理流程: + 1. 遍历 _decorated_funcs 中所有带装饰标记的函数 + 2. 对每个函数,按装饰器列表从底到顶生成嵌套 wrapper + 3. 将原函数改为 internal 链接 + 4. 替换所有调用点 + """ + if not hasattr(Gen, '_decorated_funcs') or not Gen._decorated_funcs: + return + + module = Gen.module + decorated = Gen._decorated_funcs.copy() + + for mangled_name, info in decorated.items(): + decorators = info['decorators'] + func_name = info['func_name'] + is_export = info['is_export'] + + # 查找原始函数 + original_func = None + for f in module.functions: + if f.name == mangled_name: + original_func = f + break + if original_func is None: + continue + + # 原函数改为 internal 链接(仅 wrapper 调用) + original_func.linkage = 'internal' + + # 按装饰器列表从底到顶生成嵌套 wrapper + # Python 装饰器顺序:@a @b def f() => a(b(f)) + # 执行顺序:先应用最靠近函数的 @b,再应用 @a + + current_func = original_func + all_wrapper_names = set() + + for i in range(len(decorators) - 1, -1, -1): + deco = decorators[i] + is_outermost = (i == 0) + deco_name = deco['name'] + + if is_outermost: + wrapper_name = f"__decor_wrap_{mangled_name}" + else: + wrapper_name = f"__decor_wrap_{mangled_name}_{deco_name}" + + all_wrapper_names.add(wrapper_name) + + wrapper = _generate_single_wrapper( + module, current_func, wrapper_name, + func_name, deco, is_export=is_export, + is_outermost=is_outermost, + true_original_func=original_func if is_outermost else None + ) + current_func = wrapper + + # 更新 functions 映射,使原函数名指向最外层 wrapper + Gen.functions[mangled_name] = current_func + if func_name in Gen.functions: + Gen.functions[func_name] = current_func + + # 替换所有非 wrapper 函数中对原函数的调用 + _redirect_calls(module, original_func, current_func, all_wrapper_names) diff --git a/lib/core/export_table.py b/lib/core/Exportable.py similarity index 93% rename from lib/core/export_table.py rename to lib/core/Exportable.py index e206be1..00d6c01 100644 --- a/lib/core/export_table.py +++ b/lib/core/Exportable.py @@ -1,177 +1,177 @@ -#!/usr/bin/env python3 -""" -导出表模块 - 用于收集和存储文件的公开符号信息 -""" -from dataclasses import dataclass, field -from typing import Dict, List, Optional, Any - - -@dataclass -class EnumMember: - """枚举成员信息""" - name: str - value: int - lineno: int - - -@dataclass -class EnumInfo: - """枚举类型信息""" - name: str - members: List[EnumMember] = field(default_factory=list) - lineno: int = 0 - is_public: bool = True - - -@dataclass -class FunctionParam: - """函数参数信息""" - name: str - type_name: str - is_pointer: bool = False - - -@dataclass -class FunctionInfo: - """函数信息""" - name: str - return_type: str - params: List[FunctionParam] = field(default_factory=list) - lineno: int = 0 - is_public: bool = True - - -@dataclass -class StructMember: - """结构体成员信息""" - name: str - type_name: str - is_pointer: bool = False - array_size: Optional[int] = None - - -@dataclass -class StructInfo: - """结构体类型信息""" - name: str - members: List[StructMember] = field(default_factory=list) - lineno: int = 0 - is_public: bool = True - - -@dataclass -class TypedefInfo: - """类型别名信息""" - name: str - original_type: str - lineno: int = 0 - is_public: bool = True - - -@dataclass -class ExportTable: - """导出表 - 存储文件的所有公开符号""" - filename: str - enums: List[EnumInfo] = field(default_factory=list) - functions: List[FunctionInfo] = field(default_factory=list) - structs: List[StructInfo] = field(default_factory=list) - typedefs: List[TypedefInfo] = field(default_factory=list) - - def add_enum(self, name: str, lineno: int, is_public: bool = True) -> EnumInfo: - """添加枚举类型""" - enum_info = EnumInfo(name=name, lineno=lineno, is_public=is_public) - self.enums.append(enum_info) - return enum_info - - def add_function(self, name: str, return_type: str, lineno: int, is_public: bool = True) -> FunctionInfo: - """添加函数""" - func_info = FunctionInfo(name=name, return_type=return_type, lineno=lineno, is_public=is_public) - self.functions.append(func_info) - return func_info - - def add_struct(self, name: str, lineno: int, is_public: bool = True) -> StructInfo: - """添加结构体""" - struct_info = StructInfo(name=name, lineno=lineno, is_public=is_public) - self.structs.append(struct_info) - return struct_info - - def add_typedef(self, name: str, original_type: str, lineno: int, is_public: bool = True) -> TypedefInfo: - """添加类型别名""" - typedef_info = TypedefInfo(name=name, original_type=original_type, lineno=lineno, is_public=is_public) - self.typedefs.append(typedef_info) - return typedef_info - - def to_dict(self) -> Dict[str, Any]: - """转换为字典格式""" - return { - 'filename': self.filename, - 'enums': [ - { - 'name': enum.name, - 'lineno': enum.lineno, - 'is_public': enum.is_public, - 'members': [ - {'name': m.name, 'value': m.value, 'lineno': m.lineno} - for m in enum.members - ] - } - for enum in self.enums - ], - 'functions': [ - { - 'name': func.name, - 'return_type': func.return_type, - 'lineno': func.lineno, - 'is_public': func.is_public, - 'params': [ - {'name': p.name, 'type_name': p.type_name, 'is_pointer': p.is_pointer} - for p in func.params - ] - } - for func in self.functions - ], - 'structs': [ - { - 'name': struct.name, - 'lineno': struct.lineno, - 'is_public': struct.is_public, - 'members': [ - { - 'name': m.name, - 'type_name': m.type_name, - 'is_pointer': m.is_pointer, - 'array_size': m.array_size - } - for m in struct.members - ] - } - for struct in self.structs - ], - 'typedefs': [ - { - 'name': typedef.name, - 'original_type': typedef.original_type, - 'lineno': typedef.lineno, - 'is_public': typedef.is_public - } - for typedef in self.typedefs - ] - } - - def merge(self, other: 'ExportTable') -> None: - """合并另一个导出表""" - self.enums.extend(other.enums) - self.functions.extend(other.functions) - self.structs.extend(other.structs) - self.typedefs.extend(other.typedefs) - - def get_public_symbols(self) -> 'ExportTable': - """获取仅包含公开符号的导出表""" - result = ExportTable(filename=self.filename) - - result.enums = [e for e in self.enums if e.is_public] - result.functions = [f for f in self.functions if f.is_public] - result.structs = [s for s in self.structs if s.is_public] - result.typedefs = [t for t in self.typedefs if t.is_public] - - return result +#!/usr/bin/env python3 +""" +导出表模块 - 用于收集和存储文件的公开符号信息 +""" +from dataclasses import dataclass, field +from typing import Dict, List, Optional, Any + + +@dataclass +class EnumMember: + """枚举成员信息""" + name: str + value: int + lineno: int + + +@dataclass +class EnumInfo: + """枚举类型信息""" + name: str + members: List[EnumMember] = field(default_factory=list) + lineno: int = 0 + is_public: bool = True + + +@dataclass +class FunctionParam: + """函数参数信息""" + name: str + type_name: str + is_pointer: bool = False + + +@dataclass +class FunctionInfo: + """函数信息""" + name: str + return_type: str + params: List[FunctionParam] = field(default_factory=list) + lineno: int = 0 + is_public: bool = True + + +@dataclass +class StructMember: + """结构体成员信息""" + name: str + type_name: str + is_pointer: bool = False + array_size: Optional[int] = None + + +@dataclass +class StructInfo: + """结构体类型信息""" + name: str + members: List[StructMember] = field(default_factory=list) + lineno: int = 0 + is_public: bool = True + + +@dataclass +class TypedefInfo: + """类型别名信息""" + name: str + original_type: str + lineno: int = 0 + is_public: bool = True + + +@dataclass +class Exportable: + """导出表 - 存储文件的所有公开符号""" + filename: str + enums: List[EnumInfo] = field(default_factory=list) + functions: List[FunctionInfo] = field(default_factory=list) + structs: List[StructInfo] = field(default_factory=list) + typedefs: List[TypedefInfo] = field(default_factory=list) + + def add_enum(self, name: str, lineno: int, is_public: bool = True) -> EnumInfo: + """添加枚举类型""" + enum_info = EnumInfo(name=name, lineno=lineno, is_public=is_public) + self.enums.append(enum_info) + return enum_info + + def add_function(self, name: str, return_type: str, lineno: int, is_public: bool = True) -> FunctionInfo: + """添加函数""" + func_info = FunctionInfo(name=name, return_type=return_type, lineno=lineno, is_public=is_public) + self.functions.append(func_info) + return func_info + + def add_struct(self, name: str, lineno: int, is_public: bool = True) -> StructInfo: + """添加结构体""" + struct_info = StructInfo(name=name, lineno=lineno, is_public=is_public) + self.structs.append(struct_info) + return struct_info + + def add_typedef(self, name: str, original_type: str, lineno: int, is_public: bool = True) -> TypedefInfo: + """添加类型别名""" + typedef_info = TypedefInfo(name=name, original_type=original_type, lineno=lineno, is_public=is_public) + self.typedefs.append(typedef_info) + return typedef_info + + def to_dict(self) -> Dict[str, Any]: + """转换为字典格式""" + return { + 'filename': self.filename, + 'enums': [ + { + 'name': enum.name, + 'lineno': enum.lineno, + 'is_public': enum.is_public, + 'members': [ + {'name': m.name, 'value': m.value, 'lineno': m.lineno} + for m in enum.members + ] + } + for enum in self.enums + ], + 'functions': [ + { + 'name': func.name, + 'return_type': func.return_type, + 'lineno': func.lineno, + 'is_public': func.is_public, + 'params': [ + {'name': p.name, 'type_name': p.type_name, 'is_pointer': p.is_pointer} + for p in func.params + ] + } + for func in self.functions + ], + 'structs': [ + { + 'name': struct.name, + 'lineno': struct.lineno, + 'is_public': struct.is_public, + 'members': [ + { + 'name': m.name, + 'type_name': m.type_name, + 'is_pointer': m.is_pointer, + 'array_size': m.array_size + } + for m in struct.members + ] + } + for struct in self.structs + ], + 'typedefs': [ + { + 'name': typedef.name, + 'original_type': typedef.original_type, + 'lineno': typedef.lineno, + 'is_public': typedef.is_public + } + for typedef in self.typedefs + ] + } + + def merge(self, other: 'Exportable') -> None: + """合并另一个导出表""" + self.enums.extend(other.enums) + self.functions.extend(other.functions) + self.structs.extend(other.structs) + self.typedefs.extend(other.typedefs) + + def get_public_symbols(self) -> 'Exportable': + """获取仅包含公开符号的导出表""" + result = Exportable(filename=self.filename) + + result.enums = [e for e in self.enums if e.is_public] + result.functions = [f for f in self.functions if f.is_public] + result.structs = [s for s in self.structs if s.is_public] + result.typedefs = [t for t in self.typedefs if t.is_public] + + return result diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index 7809086..6afab8d 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -2,7 +2,7 @@ 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, CTypeInfo +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo from lib.includes import t import ast import llvmlite.ir as ir @@ -33,7 +33,7 @@ class AnnAssignHandle(BaseHandle): CastedVal = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") Gen._store(CastedVal, VarPtr) except Exception: # 回退:bitcast 失败时 alloca 新变量 - NewVar = Gen._alloca_entry(Value.type, name=VarName) + NewVar = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, NewVar) Gen.variables[VarName] = NewVar @@ -90,7 +90,7 @@ class AnnAssignHandle(BaseHandle): if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IntType) and ObjVal.type.pointee.width == 8: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{ClassName}") + ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: if IsUnion: NestedStructName = f"{ClassName}_{AttrName}" @@ -195,7 +195,7 @@ class AnnAssignHandle(BaseHandle): if Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): ArrayCount = len(Node.value.value) + 1 VarType = ir.ArrayType(ElemType, ArrayCount) - var = Gen._alloca_entry(VarType, name=VarName) + var = Gen._allocaEntry(VarType, name=VarName) Gen.variables[VarName] = var Gen._record_var_signedness(VarName, False) if Node.value and isinstance(Node.value, ast.List): @@ -267,7 +267,7 @@ class AnnAssignHandle(BaseHandle): if VarName in Gen._reg_values: OldVal = Gen._reg_values[VarName] if isinstance(OldVal.type, ir.PointerType): - var = Gen._alloca_entry(OldVal.type, name=VarName) + var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var del Gen._reg_values[VarName] @@ -294,7 +294,7 @@ class AnnAssignHandle(BaseHandle): is_vtable_class = True break if is_vtable_class: - var = Gen._alloca_entry(InitValue.type, name=VarName) + var = Gen._allocaEntry(InitValue.type, name=VarName) Gen._store(InitValue, var) Gen.variables[VarName] = var if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs: @@ -329,7 +329,7 @@ class AnnAssignHandle(BaseHandle): Gen.variables[VarName] = GVar Gen._record_var_signedness(VarName, IsUnsigned) return - var = Gen._alloca_entry(VarType, name=VarName) + var = Gen._allocaEntry(VarType, name=VarName) if InitValue and isinstance(InitValue.type, ir.PointerType): pointee = InitValue.type.pointee if isinstance(pointee, ir.IdentifiedStructType): @@ -340,7 +340,7 @@ class AnnAssignHandle(BaseHandle): is_vtable_class = True break if is_vtable_class and not isinstance(VarType, ir.PointerType): - var = Gen._alloca_entry(InitValue.type, name=VarName) + var = Gen._allocaEntry(InitValue.type, name=VarName) VarType = InitValue.type IsPtr = True Gen._store(InitValue, var) @@ -356,7 +356,7 @@ class AnnAssignHandle(BaseHandle): Gen.var_struct_class[VarName] = CN Gen.global_struct_class[VarName] = CN if isinstance(VarType, ir.PointerType) and VarType.pointee is not ST and VarType.pointee != ST: - var = Gen._alloca_entry(ir.PointerType(pointee), name=VarName) + var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName) VarType = ir.PointerType(pointee) break if InitValue: @@ -435,8 +435,12 @@ class AnnAssignHandle(BaseHandle): AttrTypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if AttrTypeInfo: AttrVarType = Gen._ctype_to_llvm(AttrTypeInfo) - except Exception as e: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") Value = self.HandleExprLlvm(Node.value, VarType=AttrVarType) if Value: self._HandleAttributeStoreLlvm(Node.target, Value) diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index e7ceb93..17161eb 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -2,7 +2,7 @@ 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, CTypeInfo, FuncMeta +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.includes import t import ast import llvmlite.ir as ir @@ -89,12 +89,12 @@ class AssignHandle: fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") fmt_var_name = f"__{VarName}_fmt" if fmt_var_name not in Gen.variables: - fmt_alloca = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) + fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) Gen.variables[fmt_var_name] = fmt_alloca Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) kind_var_name = f"__{VarName}_kind" if kind_var_name not in Gen.variables: - kind_alloca = Gen._alloca_entry(ir.IntType(32), name=kind_var_name) + kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) Gen.variables[kind_var_name] = kind_alloca Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name]) if VarName not in Gen.variables: @@ -116,12 +116,12 @@ class AssignHandle: fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") fmt_var_name = f"__{VarName}_fmt" if fmt_var_name not in Gen.variables: - fmt_alloca = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) + fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) Gen.variables[fmt_var_name] = fmt_alloca Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) kind_var_name = f"__{VarName}_kind" if kind_var_name not in Gen.variables: - kind_alloca = Gen._alloca_entry(ir.IntType(32), name=kind_var_name) + kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) Gen.variables[kind_var_name] = kind_alloca Gen.builder.store(ir.Constant(ir.IntType(32), 1), Gen.variables[kind_var_name]) if VarName not in Gen.variables: @@ -129,7 +129,7 @@ class AssignHandle: Gen.variables[VarName] = dummy_var return if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == 'va_list': - va_list_ptr = Gen._alloca_entry(ir.IntType(8).as_pointer(), name="va_list") + va_list_ptr = Gen._allocaEntry(ir.IntType(8).as_pointer(), name="va_list") Gen.variables[VarName] = va_list_ptr return IsStructCtor = (isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) @@ -147,7 +147,7 @@ class AssignHandle: if IsUnion: Value = self.HandleExprLlvm(Node.value) if Value: - var = Gen._alloca_entry(Value.type, name=VarName) + var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var return @@ -160,7 +160,7 @@ class AssignHandle: elif VarName in Gen._reg_values: OldVal = Gen._reg_values[VarName] if isinstance(OldVal.type, ir.PointerType): - var = Gen._alloca_entry(OldVal.type, name=VarName) + var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var del Gen._reg_values[VarName] @@ -168,7 +168,7 @@ class AssignHandle: elif VarName in Gen._direct_values: OldVal = Gen._direct_values.pop(VarName) if isinstance(OldVal.type, ir.PointerType): - var = Gen._alloca_entry(OldVal.type, name=VarName) + var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var ExistingPtr = var @@ -195,7 +195,7 @@ class AssignHandle: return if isinstance(Value.type, ir.VoidType): return - Gen._unregister_temp_ptr(Value) + Gen._UnregisterTempPtr(Value) if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): found_class = None found = Gen.find_struct_by_pointee(Value.type.pointee) @@ -219,7 +219,7 @@ class AssignHandle: if VarName in Gen.variables and Gen.variables[VarName] is not None: Gen._store(Value, Gen.variables[VarName]) else: - var = Gen._alloca_entry(Value.type, name=VarName) + var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): @@ -231,17 +231,17 @@ class AssignHandle: dst_fmt_var = f"__{VarName}_fmt" if src_fmt_var in Gen.variables: if dst_fmt_var not in Gen.variables: - dst_alloca = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) + dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) Gen.variables[dst_fmt_var] = dst_alloca - src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"load_{call_func_name}_fmt_for_{VarName}") + src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) src_kind_var = f"__{call_func_name}_kind" dst_kind_var = f"__{VarName}_kind" if src_kind_var in Gen.variables: if dst_kind_var not in Gen.variables: - dst_kind_alloca = Gen._alloca_entry(ir.IntType(32), name=dst_kind_var) + dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) Gen.variables[dst_kind_var] = dst_kind_alloca - src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"load_{call_func_name}_kind_for_{VarName}") + src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} return @@ -260,13 +260,13 @@ class AssignHandle: return if VarName in Gen._reg_values: OldVal = Gen._reg_values[VarName] - var = Gen._alloca_entry(OldVal.type, name=VarName) + var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var del Gen._reg_values[VarName] if VarName in Gen._direct_values: OldVal = Gen._direct_values.pop(VarName) - var = Gen._alloca_entry(OldVal.type, name=VarName) + var = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var if VarName in Gen.variables and Gen.variables[VarName] is not None: @@ -277,12 +277,12 @@ class AssignHandle: except AssertionError: types_differ = False if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): - LoadedValue = Gen._load(Value, name=f"load_{VarName}") + LoadedValue = Gen._load(Value, name=f"Load_{VarName}") try: - loaded_differ = TargetType and LoadedValue.type != TargetType + Loaded_differ = TargetType and LoadedValue.type != TargetType except AssertionError: - loaded_differ = False - if loaded_differ: + Loaded_differ = False + if Loaded_differ: try: Coerced = Gen._coerce_value(LoadedValue, TargetType) if Coerced is not None: @@ -308,12 +308,12 @@ class AssignHandle: Gen._store(Value, GVar) Gen.variables[VarName] = GVar elif isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): - LoadedValue = Gen._load(Value, name=f"load_{VarName}") - var = Gen._alloca_entry(LoadedValue.type, name=VarName) + LoadedValue = Gen._load(Value, name=f"Load_{VarName}") + var = Gen._allocaEntry(LoadedValue.type, name=VarName) Gen._store(LoadedValue, var) Gen.variables[VarName] = var else: - var = Gen._alloca_entry(Value.type, name=VarName) + var = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, var) Gen.variables[VarName] = var is_u = Gen._check_node_unsigned(Node.value) @@ -327,17 +327,17 @@ class AssignHandle: dst_fmt_var = f"__{VarName}_fmt" if src_fmt_var in Gen.variables: if dst_fmt_var not in Gen.variables: - dst_alloca = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) + dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) Gen.variables[dst_fmt_var] = dst_alloca - src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"load_{call_func_name}_fmt_for_{VarName}") + src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) src_kind_var = f"__{call_func_name}_kind" dst_kind_var = f"__{VarName}_kind" if src_kind_var in Gen.variables: if dst_kind_var not in Gen.variables: - dst_kind_alloca = Gen._alloca_entry(ir.IntType(32), name=dst_kind_var) + dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) Gen.variables[dst_kind_var] = dst_kind_alloca - src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"load_{call_func_name}_kind_for_{VarName}") + src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} else: @@ -403,12 +403,12 @@ class AssignHandle: elif isinstance(Target, ast.Tuple): if isinstance(Node.value, ast.Call): FuncName = None - module_path = None + ModulePath = None if isinstance(Node.value.func, ast.Name): FuncName = Node.value.func.id elif isinstance(Node.value.func, ast.Attribute): FuncName = Node.value.func.attr - module_path = self.Trans.ExprCallHandle._get_module_path(Node.value.func.value) + ModulePath = self.Trans.ExprCallHandle._get_ModulePath(Node.value.func.value) CReturnTypes = [] FuncDef = self.Trans.FunctionDefCache.get(FuncName) if FuncName else None if FuncDef: @@ -436,8 +436,8 @@ class AssignHandle: if not CReturnTypes: sym_key = FuncName if sym_key not in self.Trans.SymbolTable: - if module_path: - sym_key = f"{module_path}.{FuncName}" + if ModulePath: + sym_key = f"{ModulePath}.{FuncName}" sym_info = self.Trans.SymbolTable.get(sym_key) if sym_info and sym_info.IsFunction: ret_type_info = getattr(sym_info, 'FuncPtrReturn', None) @@ -604,7 +604,7 @@ class AssignHandle: CastedVal = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") Gen._store(CastedVal, VarPtr) except Exception: # 回退:bitcast 失败时 alloca 新变量 - NewVar = Gen._alloca_entry(Value.type, name=VarName) + NewVar = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, NewVar) Gen.variables[VarName] = NewVar @@ -620,7 +620,7 @@ class AssignHandle: SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") - SetterFunc = Gen._get_function(PropKey) + SetterFunc = Gen._get_function(PropKey + '$set') if SetterFunc and SelfPtr: Gen.builder.call(SetterFunc, [SelfPtr, Value], name=f"prop_set_{PropKey}") return @@ -683,7 +683,7 @@ class AssignHandle: if offset >= max_offset: VarName = f"self.{AttrName}" if VarName not in Gen.variables: - NewVar = Gen._alloca_entry(Value.type, name=AttrName) + NewVar = Gen._allocaEntry(Value.type, name=AttrName) Gen.variables[VarName] = NewVar Gen._store(Value, Gen.variables[VarName]) return @@ -736,10 +736,10 @@ class AssignHandle: PropInfo = self.Trans.SymbolTable.get(PropKey) if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - SetterFunc = Gen._get_function(PropKey) + SetterFunc = Gen._get_function(PropKey + '$set') if SetterFunc and ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{ClassName}") + ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") Gen.builder.call(SetterFunc, [ObjVal, Value], name=f"prop_set_{PropKey}") return ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) @@ -747,7 +747,7 @@ class AssignHandle: if BaseHandle._is_char_pointer(ObjVal): ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{ClassName}") + ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: if IsUnion: NestedStructName = f"{ClassName}_{AttrName}" @@ -855,8 +855,8 @@ class AssignHandle: self._StoreWithCoerce(Value, MemberPtr) if not ClassName: - imported_modules = getattr(self.Trans, '_imported_modules', None) - import_aliases = getattr(self.Trans, '_import_aliases', {}) + imported_modules = getattr(self.Trans, '_ImportedModules', None) + import_aliases = getattr(self.Trans, '_ImportAliases', {}) resolved_mod = import_aliases.get(VarName, VarName) if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): PossibleKeys = [f"{VarName}.{AttrName}", AttrName] @@ -874,14 +874,14 @@ class AssignHandle: return self._StoreWithCoerce(Value, GVar) return - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) sha1_candidates = [VarName, resolved_mod] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: if mod_name not in sha1_candidates: sha1_candidates.append(mod_name) for cand in sha1_candidates: - sha1 = module_sha1_map.get(cand) + sha1 = ModuleSha1Map.get(cand) if sha1: prefixed = f"{sha1}.{AttrName}" if prefixed in Gen.module.globals: @@ -945,7 +945,7 @@ class AssignHandle: self._StoreWithCoerce(Value, MemberPtr) return elif isinstance(Target.value, ast.Call): - # Check if this is c.Deref(...) — we need the pointer, not the loaded value + # Check if this is c.Deref(...) — we need the pointer, not the Loaded value ObjVal = None is_cderef = (isinstance(Target.value.func, ast.Attribute) and isinstance(Target.value.func.value, ast.Name) and @@ -953,7 +953,7 @@ class AssignHandle: Target.value.func.attr == 'Deref' and Target.value.args) if is_cderef: - # Get the pointer from c.Deref argument, don't load the value + # Get the pointer from c.Deref argument, don't Load the value deref_arg = Target.value.args[0] inner_val = self.HandleExprLlvm(deref_arg) if inner_val and isinstance(inner_val.type, ir.PointerType): @@ -1019,7 +1019,7 @@ class AssignHandle: MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) elif isinstance(pointee, ir.PointerType): - LoadedPtr = Gen._load(SubPtr, name=f"load_{AttrName}_ptr") + LoadedPtr = Gen._load(SubPtr, name=f"Load_{AttrName}_ptr") if isinstance(LoadedPtr.type, ir.PointerType) and isinstance(LoadedPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): found = Gen.find_struct_by_pointee(LoadedPtr.type.pointee) if found: @@ -1049,8 +1049,8 @@ class AssignHandle: if not ValueVal or not IndexVal: return if BaseHandle._is_char_pointer(IndexVal): - loaded_byte = Gen._load(IndexVal, name="load_char_idx_store") - IndexVal = Gen.builder.zext(loaded_byte, ir.IntType(32), name="char_to_int_idx_store") + Loaded_byte = Gen._load(IndexVal, name="Load_char_idx_store") + IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_store") if isinstance(ValueVal.type, ir.IntType): var_ptr = self._get_int_ptr(Target.value) if var_ptr: @@ -1116,7 +1116,7 @@ class AssignHandle: ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) return - arr_alloc = Gen._alloca_entry(ValueVal.type, name="arr_subscript_tmp") + arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") Gen._store(ValueVal, arr_alloc) ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") self._StoreWithCoerce(Value, ElemPtr) diff --git a/lib/core/Handles/HandlesAugAssign.py b/lib/core/Handles/HandlesAugAssign.py index 575bd6e..a8cf11d 100644 --- a/lib/core/Handles/HandlesAugAssign.py +++ b/lib/core/Handles/HandlesAugAssign.py @@ -1,212 +1,212 @@ -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 ast -import llvmlite.ir as ir - - -class AugAssignHandle(BaseHandle): - _AUGOP_MAP = { - ast.Add: '__iadd__', ast.Sub: '__isub__', ast.Mult: '__imul__', - ast.Div: '__itruediv__', ast.FloorDiv: '__ifloordiv__', ast.Mod: '__imod__', ast.Pow: '__ipow__', - } - _AUGOP_FALLBACK = { - ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', - ast.Div: '__truediv__', ast.FloorDiv: '__floordiv__', ast.Mod: '__mod__', ast.Pow: '__pow__', - } - - def _is_aug_unsigned(self, Node, OldVal, Value): - """判断增量赋值操作是否应使用无符号指令""" - Gen = self.Trans.LlvmGen - if isinstance(Node.target, ast.Name): - if Gen._check_node_unsigned(Node.target): - return True - elif isinstance(Node.target, ast.Attribute): - if Gen._check_node_unsigned(Node.target): - return True - elif isinstance(Node.target, ast.Subscript): - if Gen._check_node_unsigned(Node.target): - return True - if Node.value is not None and Gen._check_node_unsigned(Node.value): - return True - return False - - def _HandleAugAssignLlvm(self, Node): - Gen = self.Trans.LlvmGen - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - if VarName in Gen.var_const_flags: - src_info = Gen._get_node_info() - print(f"[错误] 不能对 const 变量 '{VarName}' 增量赋值{src_info}") - import sys - sys.exit(1) - ClassName = Gen.var_struct_class.get(VarName) - iop_name = self._AUGOP_MAP.get(type(Node.op)) - if ClassName and iop_name: - iFuncName = f'{ClassName}.{iop_name}' - FuncName = f'{ClassName}.{self._AUGOP_FALLBACK.get(type(Node.op), "")}' - if iFuncName in Gen.functions or FuncName in Gen.functions: - OldVal = self.Trans.ExprHandler.HandleExprLlvm(ast.Name(id=VarName, ctx=ast.Load())) - Value = self.HandleExprLlvm(Node.value) - if OldVal and Value: - if iFuncName in Gen.functions: - result = self.Trans.ExprHandler._try_operator_overload(ClassName, iop_name, OldVal, Gen, Value) - else: - result = self.Trans.ExprHandler._try_operator_overload(ClassName, self._AUGOP_FALLBACK[type(Node.op)], OldVal, Gen, Value) - if result is not None: - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if VarPtr.type.pointee == result.type: - Gen._store(result, VarPtr) - elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(result.type, ir.PointerType): - CastedVal = Gen.builder.bitcast(result, VarPtr.type.pointee, name=f"cast_{VarName}") - Gen._store(CastedVal, VarPtr) - else: - NewVar = Gen._alloca_entry(result.type, name=VarName) - Gen._store(result, NewVar) - Gen.variables[VarName] = NewVar - else: - Gen._reg_values[VarName] = result - Gen.variables[VarName] = None - return - Value = self.HandleExprLlvm(Node.value) - if not Value: - return - is_unsigned = self._is_aug_unsigned(Node, None, Value) - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if VarName in Gen.global_vars and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - OldVal = Gen._load(GVar, name=VarName) - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - Gen._store(NewVal, GVar) - return - if VarName in Gen._reg_values: - OldVal = Gen._reg_values[VarName] - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = Gen.builder.alloca(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 = Gen._direct_values.pop(VarName) - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = Gen.builder.alloca(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 - if VarName in Gen.variables and Gen.variables[VarName] is not None: - OldVal = Gen._load(Gen.variables[VarName], name=VarName) - store_ptr = Gen.variables[VarName] - if isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Value.type.width != 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset") - if Op == '-' or Op == '+': - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add") - else: - ptr_val = OldVal - OldVal = Gen._load(OldVal, name="deref_ptr_for_op") - orig_type = OldVal.type - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(NewVal.type, ir.IntType) and isinstance(orig_type, ir.IntType): - if NewVal.type.width > orig_type.width: - NewVal = Gen.builder.trunc(NewVal, orig_type, name="trunc_result") - store_ptr = ptr_val - else: - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") - elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Op in ('+', '-'): - if Value.type.width < 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_aug") - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_aug") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_aug") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_aug") - Gen._store(NewVal, store_ptr) - return - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(store_ptr.type, ir.PointerType): - TargetType = store_ptr.type.pointee - if NewVal.type != TargetType: - Coerced = Gen._coerce_value(NewVal, TargetType) - if Coerced is not None: - NewVal = Coerced - Gen._store(NewVal, store_ptr) - elif VarName == 'pos': - var = Gen._alloca_entry(Value.type, name=VarName) - Gen.variables[VarName] = var - OldVal = Gen._load(var, name=VarName) - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - Gen._store(NewVal, var) - elif isinstance(Node.target, ast.Attribute): - AttrName = Node.target.attr - OldVal = self.Trans.ExprHandler.HandleExprLlvm(Node.target) - if OldVal: - def _deref_if_ptr(val): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): - return Gen._load(val, name="deref_aug") - return val - OldVal = _deref_if_ptr(OldVal) - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_attr") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_attr") - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - self.Trans.AssignHandler._HandleAttributeStoreLlvm(Node.target, NewVal) - elif isinstance(Node.target, ast.Subscript): - SubTarget = Node.target - ElemPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(SubTarget) - if ElemPtr: - if isinstance(ElemPtr.type, ir.PointerType): - OldVal = Gen._load(ElemPtr, name="old_subscript_val") - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_sub") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_sub") - elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Op in ('+', '-'): - if Value.type.width < 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_sub") - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_sub") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_sub") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_sub") - Gen._store(NewVal, ElemPtr) - return - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(NewVal.type, ir.IntType) and isinstance(ElemPtr.type.pointee, ir.IntType): - if NewVal.type.width > ElemPtr.type.pointee.width: - NewVal = Gen.builder.trunc(NewVal, ElemPtr.type.pointee, name="trunc_sub_result") - Gen._store(NewVal, ElemPtr) +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 ast +import llvmlite.ir as ir + + +class AugAssignHandle(BaseHandle): + _AUGOP_MAP = { + ast.Add: '__iadd__', ast.Sub: '__isub__', ast.Mult: '__imul__', + ast.Div: '__itruediv__', ast.FloorDiv: '__ifloordiv__', ast.Mod: '__imod__', ast.Pow: '__ipow__', + } + _AUGOP_FALLBACK = { + ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', + ast.Div: '__truediv__', ast.FloorDiv: '__floordiv__', ast.Mod: '__mod__', ast.Pow: '__pow__', + } + + def _is_aug_unsigned(self, Node, OldVal, Value): + """判断增量赋值操作是否应使用无符号指令""" + Gen = self.Trans.LlvmGen + if isinstance(Node.target, ast.Name): + if Gen._check_node_unsigned(Node.target): + return True + elif isinstance(Node.target, ast.Attribute): + if Gen._check_node_unsigned(Node.target): + return True + elif isinstance(Node.target, ast.Subscript): + if Gen._check_node_unsigned(Node.target): + return True + if Node.value is not None and Gen._check_node_unsigned(Node.value): + return True + return False + + def _HandleAugAssignLlvm(self, Node): + Gen = self.Trans.LlvmGen + if isinstance(Node.target, ast.Name): + VarName = Node.target.id + if VarName in Gen.var_const_flags: + src_info = Gen._get_node_info() + print(f"[错误] 不能对 const 变量 '{VarName}' 增量赋值{src_info}") + import sys + sys.exit(1) + ClassName = Gen.var_struct_class.get(VarName) + iop_name = self._AUGOP_MAP.get(type(Node.op)) + if ClassName and iop_name: + iFuncName = f'{ClassName}.{iop_name}' + FuncName = f'{ClassName}.{self._AUGOP_FALLBACK.get(type(Node.op), "")}' + if iFuncName in Gen.functions or FuncName in Gen.functions: + OldVal = self.Trans.ExprHandler.HandleExprLlvm(ast.Name(id=VarName, ctx=ast.Load())) + Value = self.HandleExprLlvm(Node.value) + if OldVal and Value: + if iFuncName in Gen.functions: + result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, iop_name, OldVal, Gen, Value) + else: + result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, self._AUGOP_FALLBACK[type(Node.op)], OldVal, Gen, Value) + if result is not None: + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr = Gen.variables[VarName] + if VarPtr.type.pointee == result.type: + Gen._store(result, VarPtr) + elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(result.type, ir.PointerType): + CastedVal = Gen.builder.bitcast(result, VarPtr.type.pointee, name=f"cast_{VarName}") + Gen._store(CastedVal, VarPtr) + else: + NewVar = Gen._allocaEntry(result.type, name=VarName) + Gen._store(result, NewVar) + Gen.variables[VarName] = NewVar + else: + Gen._reg_values[VarName] = result + Gen.variables[VarName] = None + return + Value = self.HandleExprLlvm(Node.value) + if not Value: + return + is_unsigned = self._is_aug_unsigned(Node, None, Value) + if isinstance(Node.target, ast.Name): + VarName = Node.target.id + Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if VarName in Gen.global_vars and VarName in Gen.module.globals: + GVar = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + OldVal = Gen._load(GVar, name=VarName) + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + Gen._store(NewVal, GVar) + return + if VarName in Gen._reg_values: + OldVal = Gen._reg_values[VarName] + saved_block = Gen.builder.block + entry_block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var = Gen.builder.alloca(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 = Gen._direct_values.pop(VarName) + saved_block = Gen.builder.block + entry_block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var = Gen.builder.alloca(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 + if VarName in Gen.variables and Gen.variables[VarName] is not None: + OldVal = Gen._load(Gen.variables[VarName], name=VarName) + store_ptr = Gen.variables[VarName] + if isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Value.type.width != 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset") + if Op == '-' or Op == '+': + if Op == '-': + NegValue = Gen.builder.neg(Value, name="neg_ptr_offset") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add") + else: + ptr_val = OldVal + OldVal = Gen._load(OldVal, name="deref_ptr_for_op") + orig_type = OldVal.type + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(NewVal.type, ir.IntType) and isinstance(orig_type, ir.IntType): + if NewVal.type.width > orig_type.width: + NewVal = Gen.builder.trunc(NewVal, orig_type, name="trunc_result") + store_ptr = ptr_val + else: + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") + elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Op in ('+', '-'): + if Value.type.width < 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_aug") + if Op == '-': + NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_aug") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_aug") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_aug") + Gen._store(NewVal, store_ptr) + return + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(store_ptr.type, ir.PointerType): + TargetType = store_ptr.type.pointee + if NewVal.type != TargetType: + Coerced = Gen._coerce_value(NewVal, TargetType) + if Coerced is not None: + NewVal = Coerced + Gen._store(NewVal, store_ptr) + elif VarName == 'pos': + var = Gen._allocaEntry(Value.type, name=VarName) + Gen.variables[VarName] = var + OldVal = Gen._load(var, name=VarName) + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + Gen._store(NewVal, var) + elif isinstance(Node.target, ast.Attribute): + AttrName = Node.target.attr + OldVal = self.Trans.ExprHandler.HandleExprLlvm(Node.target) + if OldVal: + def _deref_if_ptr(val): + if isinstance(val.type, ir.PointerType): + pointee = val.type.pointee + if isinstance(pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): + return Gen._load(val, name="deref_aug") + return val + OldVal = _deref_if_ptr(OldVal) + Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_attr") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_attr") + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + self.Trans.AssignHandler._HandleAttributeStoreLlvm(Node.target, NewVal) + elif isinstance(Node.target, ast.Subscript): + SubTarget = Node.target + ElemPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(SubTarget) + if ElemPtr: + if isinstance(ElemPtr.type, ir.PointerType): + OldVal = Gen._load(ElemPtr, name="old_subscript_val") + Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_sub") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_sub") + elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Op in ('+', '-'): + if Value.type.width < 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_sub") + if Op == '-': + NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_sub") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_sub") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_sub") + Gen._store(NewVal, ElemPtr) + return + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(NewVal.type, ir.IntType) and isinstance(ElemPtr.type.pointee, ir.IntType): + if NewVal.type.width > ElemPtr.type.pointee.width: + NewVal = Gen.builder.trunc(NewVal, ElemPtr.type.pointee, name="trunc_sub_result") + Gen._store(NewVal, ElemPtr) diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 60b7983..94d0b9b 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Dict, Tuple if TYPE_CHECKING: from lib.core.translator import Translator from lib.constants import config as _config @@ -950,7 +950,7 @@ class CTypeInfo: if ModulePath: resolved = False if hasattr(SymbolTable, 'translator'): - import_aliases = getattr(SymbolTable.translator, '_import_aliases', {}) + import_aliases = getattr(SymbolTable.translator, '_ImportAliases', {}) if ModulePath in import_aliases: ModulePath = import_aliases[ModulePath] resolved = True @@ -1056,10 +1056,10 @@ class CTypeInfo: if OriginalType and 'typedef' in OriginalType: parts = OriginalType.split() if len(parts) >= 2: - base_type_name = parts[1] - if not base_type_name.startswith('C'): - base_type_name = 'C' + base_type_name - CNAME = CTypeHelper.GetCName(base_type_name) + BaseType_name = parts[1] + if not BaseType_name.startswith('C'): + BaseType_name = 'C' + BaseType_name + CNAME = CTypeHelper.GetCName(BaseType_name) if CNAME: return cls.FromTypeName(CNAME) Result = cls() diff --git a/lib/core/Handles/HandlesBody.py b/lib/core/Handles/HandlesBody.py index 63a8d48..e236783 100644 --- a/lib/core/Handles/HandlesBody.py +++ b/lib/core/Handles/HandlesBody.py @@ -67,10 +67,10 @@ class BodyHandle(BaseHandle): line_info = "源代码 (%s, line %d)" % (src_path, lineno) if source_line: line_info += ":\n %d | %s" % (lineno, source_line) - self.Trans._error_stack.append((type(e).__name__, str(e), line_info)) + self.Trans._ErrorStack.append((type(e).__name__, str(e), line_info)) raise if Gen.builder and not Gen.builder.block.is_terminated: - Gen._emit_temp_frees() + Gen._EmitTempFrees() def HandleExprLlvm(self, Node, VarType=None): return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 29df85a..9c72ecb 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -2,7 +2,7 @@ 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, CTypeInfo +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.core.SymbolNode import SymbolNode from lib.includes import t import ast @@ -345,6 +345,12 @@ class ClassHandle(BaseHandle): if isinstance(item, ast.FunctionDef): MethodName = item.name FullMethodName = f"{ClassName}.{MethodName}" + # property setter/deleter 使用不同的函数名后缀 + item_meta = self.Trans.FunctionHandler._ExtractFuncMeta(item.decorator_list) + if FuncMeta.PROPERTY_SETTER in item_meta: + FullMethodName = FullMethodName + '$set' + elif FuncMeta.PROPERTY_DELETER in item_meta: + FullMethodName = FullMethodName + '$del' if FullMethodName not in Gen.class_methods[ClassName]: Gen.class_methods[ClassName].append(FullMethodName) Gen.register_method(ClassName, FullMethodName) @@ -781,8 +787,8 @@ class ClassHandle(BaseHandle): EnumTypeInfo.BaseType = t.CEnum(ClassName) EnumTypeInfo.IsEnum = True self.Trans.SymbolTable[ClassName] = EnumTypeInfo - from lib.core.export_table import EnumMember as ExportEnumMember - enum_export = self.Trans.ExportTable.add_enum( + from lib.core.Exportable import EnumMember as ExportEnumMember + enum_export = self.Trans.Exportable.add_enum( name=ClassName, lineno=Node.lineno, is_public=True diff --git a/lib/core/Handles/HandlesDelete.py b/lib/core/Handles/HandlesDelete.py index a511244..243733b 100644 --- a/lib/core/Handles/HandlesDelete.py +++ b/lib/core/Handles/HandlesDelete.py @@ -44,7 +44,7 @@ class DeleteHandle(BaseHandle): SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") - DeleterFunc = Gen._get_function(PropKey) + DeleterFunc = Gen._get_function(PropKey + '$del') if DeleterFunc and SelfPtr: Gen.builder.call(DeleterFunc, [SelfPtr], name=f"prop_del_{PropKey}") continue @@ -57,7 +57,7 @@ class DeleteHandle(BaseHandle): if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value) if obj_val: - DeleterFunc = Gen._get_function(PropKey) + DeleterFunc = Gen._get_function(PropKey + '$del') if DeleterFunc: Gen.builder.call(DeleterFunc, [obj_val], name=f"prop_del_{PropKey}") continue @@ -66,7 +66,7 @@ class DeleteHandle(BaseHandle): obj_val = self.Trans.ExprHandler.HandleExprLlvm(target) if obj_val: if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.PointerType): - obj_val = Gen._load(obj_val, name="load_del_ptr") + obj_val = Gen._load(obj_val, name="Load_del_ptr") ClassName = None if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): for CN, ST in Gen.structs.items(): diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index 956994b..dbf117c 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -1,429 +1,429 @@ -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 ast -import llvmlite.ir as ir - - -class ExprHandle(BaseHandle): - def __init__(self, translator: "Translator"): - super().__init__(translator) - - def GetOpSymbol(self, Op): - return self.Trans.ExprUtils.GetOpSymbol(Op) - - def GetUnaryOpSymbol(self, Op): - return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) - - def GetComparatorSymbol(self, Op): - return self.Trans.ExprUtils.GetComparatorSymbol(Op) - - def _get_var_class(self, node, Gen): - return self.Trans.ExprUtils._get_var_class(node, Gen) - - def _try_operator_overload(self, ClassName, op_name, obj_val, Gen, other_val=None): - return self.Trans.ExprUtils._try_operator_overload(ClassName, op_name, obj_val, Gen, other_val) - - def _get_llvm_member_offset(self, field_name, ClassName, Gen): - return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) - - def HandleExprLlvm(self, Node, VarType=None): - Gen = 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): - in_str_method = getattr(Gen, 'func', None) and getattr(Gen.func, 'name', '').endswith('.__str__') - return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node, return_str=in_str_method) - 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, VarType=None): - Gen = self.Trans.LlvmGen - elements = Node.elts - if not elements: - return ir.Constant(ir.IntType(8).as_pointer(), None) - - array_len = len(elements) - elem_type = 'i8' - - if VarType and isinstance(VarType, str) and 'list[' in VarType: - import re - match = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) - if match: - type_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 = array_len - if elem_type == 'i32': - alloc_size *= 4 - elif elem_type == 'i16': - alloc_size *= 2 - elif elem_type == 'float': - alloc_size *= 4 - elif elem_type == 'double': - alloc_size *= 8 - - malloc_fn = None - malloc_arg_type = ir.IntType(64) - for fn in Gen.module.global_values: - if fn.name == 'malloc': - malloc_fn = fn - func_ftype = 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.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 = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) - cast_ptr = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) - - for i, elem in enumerate(elements): - if i >= array_len: - break - - elem_val = self.HandleExprLlvm(elem, VarType=elem_type) - if elem_val is None: - continue - - byte_offset = 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 = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) - new_ptr_val = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) - if elem_type == 'i32': - elem_ptr = 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 == 'float': - return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.FloatType()), name="list_float_ptr") - elif elem_type == 'double': - return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.DoubleType()), name="list_double_ptr") - return cast_ptr - - def _HandleConstantLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - Value = 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): - from lib.includes.t import CTypeRegistry as _CR - resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(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) - is_unsigned = getattr(inst, 'IsSigned', True) is False - mask = (1 << size) - 1 - return ir.Constant(ir.IntType(size), Value & mask) - llvm_match = __import__('re').match(r'^i(\d+)$', VarType) - if llvm_match: - width = 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 = getattr(Node, 'kind', None) == 'u' - if len(Value) == 1 and not is_wide: - if VarType is not None and isinstance(VarType, ir.PointerType): - pass - elif isinstance(VarType, ir.IntType): - return ir.Constant(VarType, ord(Value[0])) - elif isinstance(VarType, str): - from lib.includes.t import CTypeRegistry as _CR - resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(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 = __import__('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])) - if is_wide: - str_value = Value + '\x00' - wide_chars = [ord(c) for c in str_value] - target_count = len(wide_chars) - str_type = ir.ArrayType(ir.IntType(16), 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, wide_chars) - 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 - else: - str_value = Value + '\x00' - str_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, VarType=None): - Gen = self.Trans.LlvmGen - VarName = Node.id - define_constants = getattr(Gen, '_define_constants', {}) - if VarName in define_constants: - val = define_constants[VarName] - 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): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - 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 - # 如果 _define_constants 中没有,尝试从符号表查找 - if VarName not in getattr(Gen, '_define_constants', {}): - try: - sym_info = self.translator.SymbolTable.get(VarName) - if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None: - val = sym_info.DefineValue - 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): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - 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 - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = 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 - return Gen._load(VarPtr, name=VarName) - 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 = 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': - return Gen._get_var_ptr('self') - if Gen._has_function(VarName): - func = 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) - if VarName in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[VarName] - if getattr(SymInfo, 'IsEnumMember', None) and isinstance(getattr(SymInfo, 'value', None), int): - return ir.Constant(ir.IntType(32), SymInfo.value) - if getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsFuncPtr', False): - MangledName = Gen._mangle_func_name(VarName) - if MangledName in Gen.module.globals: - g = 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.module_sha1_map.values(): - prefixed = 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 = getattr(self.Trans, '_t_c_imported_names', {}) - if VarName in t_c_imported: - src_module, src_name = t_c_imported[VarName] - virtual_attr = 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) +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 ast +import llvmlite.ir as ir + + +class ExprHandle(BaseHandle): + def __init__(self, translator: "Translator"): + super().__init__(translator) + + def GetOpSymbol(self, Op): + return self.Trans.ExprUtils.GetOpSymbol(Op) + + def GetUnaryOpSymbol(self, Op): + return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) + + def GetComparatorSymbol(self, Op): + return self.Trans.ExprUtils.GetComparatorSymbol(Op) + + def _get_var_class(self, node, Gen): + return self.Trans.ExprUtils._get_var_class(node, Gen) + + def _try_operator_overLoad(self, ClassName, op_name, obj_val, Gen, other_val=None): + return self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, obj_val, Gen, other_val) + + def _get_llvm_member_offset(self, field_name, ClassName, Gen): + return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) + + def HandleExprLlvm(self, Node, VarType=None): + Gen = 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): + in_str_method = getattr(Gen, 'func', None) and getattr(Gen.func, 'name', '').endswith('.__str__') + return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node, return_str=in_str_method) + 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, VarType=None): + Gen = self.Trans.LlvmGen + elements = Node.elts + if not elements: + return ir.Constant(ir.IntType(8).as_pointer(), None) + + array_len = len(elements) + elem_type = 'i8' + + if VarType and isinstance(VarType, str) and 'list[' in VarType: + import re + match = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) + if match: + type_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 = array_len + if elem_type == 'i32': + alloc_size *= 4 + elif elem_type == 'i16': + alloc_size *= 2 + elif elem_type == 'float': + alloc_size *= 4 + elif elem_type == 'double': + alloc_size *= 8 + + malloc_fn = None + malloc_arg_type = ir.IntType(64) + for fn in Gen.module.global_values: + if fn.name == 'malloc': + malloc_fn = fn + func_ftype = 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.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 = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) + cast_ptr = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) + + for i, elem in enumerate(elements): + if i >= array_len: + break + + elem_val = self.HandleExprLlvm(elem, VarType=elem_type) + if elem_val is None: + continue + + byte_offset = 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 = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) + new_ptr_val = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) + if elem_type == 'i32': + elem_ptr = 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 == 'float': + return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.FloatType()), name="list_float_ptr") + elif elem_type == 'double': + return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.DoubleType()), name="list_double_ptr") + return cast_ptr + + def _HandleConstantLlvm(self, Node, VarType=None): + Gen = self.Trans.LlvmGen + Value = 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): + from lib.includes.t import CTypeRegistry as _CR + resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(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) + is_unsigned = getattr(inst, 'IsSigned', True) is False + mask = (1 << size) - 1 + return ir.Constant(ir.IntType(size), Value & mask) + llvm_match = __import__('re').match(r'^i(\d+)$', VarType) + if llvm_match: + width = 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 = getattr(Node, 'kind', None) == 'u' + if len(Value) == 1 and not is_wide: + if VarType is not None and isinstance(VarType, ir.PointerType): + pass + elif isinstance(VarType, ir.IntType): + return ir.Constant(VarType, ord(Value[0])) + elif isinstance(VarType, str): + from lib.includes.t import CTypeRegistry as _CR + resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(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 = __import__('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])) + if is_wide: + str_value = Value + '\x00' + wide_chars = [ord(c) for c in str_value] + target_count = len(wide_chars) + str_type = ir.ArrayType(ir.IntType(16), 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, wide_chars) + 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 + else: + str_value = Value + '\x00' + str_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, VarType=None): + Gen = self.Trans.LlvmGen + VarName = Node.id + define_constants = getattr(Gen, '_define_constants', {}) + if VarName in define_constants: + val = define_constants[VarName] + 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): + str_value = val + '\x00' + str_bytes = str_value.encode('utf-8') + str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) + 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 + # 如果 _define_constants 中没有,尝试从符号表查找 + if VarName not in getattr(Gen, '_define_constants', {}): + try: + sym_info = self.translator.SymbolTable.get(VarName) + if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None: + val = sym_info.DefineValue + 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): + str_value = val + '\x00' + str_bytes = str_value.encode('utf-8') + str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) + 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 + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr = 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 + return Gen._load(VarPtr, name=VarName) + 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 = 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': + return Gen.GetVarPtr('self') + if Gen._has_function(VarName): + func = 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) + if VarName in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[VarName] + if getattr(SymInfo, 'IsEnumMember', None) and isinstance(getattr(SymInfo, 'value', None), int): + return ir.Constant(ir.IntType(32), SymInfo.value) + if getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsFuncPtr', False): + MangledName = Gen._mangle_func_name(VarName) + if MangledName in Gen.module.globals: + g = 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 = 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 = getattr(self.Trans, '_t_c_imported_names', {}) + if VarName in t_c_imported: + src_module, src_name = t_c_imported[VarName] + virtual_attr = 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) diff --git a/lib/core/Handles/HandlesExprAsm.py b/lib/core/Handles/HandlesExprAsm.py index 004babf..886933b 100644 --- a/lib/core/Handles/HandlesExprAsm.py +++ b/lib/core/Handles/HandlesExprAsm.py @@ -1,578 +1,578 @@ -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 ast -import llvmlite.ir as ir -import t - -# 猴子补丁 llvmlite.ir.InlineAsm 以支持 asm_dialect 参数 -# 添加保护避免重复补丁 -_InlineAsmPatched = getattr(ir.InlineAsm, '_transpyc_patched', False) - -if not _InlineAsmPatched: - _OrigInlineAsmInit = ir.InlineAsm.__init__ - _OrigInlineAsmDescr = ir.InlineAsm.descr - - def _patched_inline_asm_init(self, ftype, asm, constraint, side_effect=False, asm_dialect=None): - _OrigInlineAsmInit(self, ftype, asm, constraint, side_effect) - self.asm_dialect = asm_dialect - - def _patched_inline_asm_descr(self, buf): - sideeffect = 'sideeffect' if self.side_effect else '' - dialect_str = getattr(self, 'asm_dialect', None) - if dialect_str == 'intel': - dialect = 'inteldialect' - else: - dialect = '' - fmt = 'asm {sideeffect} {dialect} "{asm}", "{constraint}"' - buf.append(fmt.format(sideeffect=sideeffect, dialect=dialect, asm=self.asm, - constraint=self.constraint)) - - ir.InlineAsm.__init__ = _patched_inline_asm_init - ir.InlineAsm.descr = _patched_inline_asm_descr - ir.InlineAsm._transpyc_patched = True - - -class ExprAsmHandle(BaseHandle): - @staticmethod - def _format_to_dialect(asm_format): - """将用户指定的 format 参数转换为 LLVM asm_dialect 值""" - fmt = asm_format.lower() if asm_format else 'intel' - if fmt == 'att': - return 'att' - elif fmt == 'arm': - return None # ARM 没有专门的 dialect 标记 - else: - return 'intel' # 默认 Intel - - def _HandleAsmLlvm(self, Node): - Gen = self.Trans.LlvmGen - - op_arg = None - input_arg = None - output_arg = None - asm_format = 'Intel' # 汇编格式: Intel / AT&T / ARM - for kw in Node.keywords: - if kw.arg == 'op': - op_arg = kw.value - elif kw.arg in ('input', 'inp', 'inputs'): - input_arg = kw.value - elif kw.arg in ('output', 'out', 'outputs'): - output_arg = kw.value - elif kw.arg == 'format': - if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str): - asm_format = kw.value.value - - if len(Node.args) >= 1: - pos_op = None - if len(Node.args) >= 2 and op_arg is None: - pos_op = Node.args[1] - return self._HandleAsmWithOpLlvm(Node.args[0], op_arg or pos_op, input_arg, output_arg, asm_format) - - if len(Node.args) < 2: - return ir.Constant(ir.IntType(32), 1) - - args = Node.args - - if len(args) == 4: - output_type_arg = args[0] - asm_template_arg = args[1] - constraint_arg = args[2] - clobber_arg = args[3] - - output_type = self._infer_expr_llvm_type(output_type_arg) - if not output_type: - output_type = ir.IntType(32) - - asm_template = '' - if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): - asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) - - constraint = '' - if isinstance(constraint_arg, ast.Constant) and isinstance(constraint_arg.value, str): - constraint = constraint_arg.value - - clobber = '' - if isinstance(clobber_arg, ast.Constant) and isinstance(clobber_arg.value, str): - clobber = clobber_arg.value - - full_constraint = constraint - func_type = ir.FunctionType(output_type, []) - asm_dialect = self._format_to_dialect(asm_format) - inline_asm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, [], name="asm_result") - return result - - elif len(args) >= 2: - output_type_arg = args[0] - asm_template_arg = args[1] - - output_type = self._infer_expr_llvm_type(output_type_arg) - if not output_type: - output_type = ir.IntType(32) - - asm_template = '' - if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): - asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) - - output_constraints = [] - output_values = [] - if len(args) > 2 and isinstance(args[2], (ast.List, ast.Tuple)): - for item in args[2].elts: - if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - constraint_node = item.elts[0] - value_node = item.elts[1] - if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): - output_constraints.append(constraint_node.value) - value = self.HandleExprLlvm(value_node) - if value: - output_values.append(value) - - input_constraints = [] - input_values = [] - if len(args) > 3 and isinstance(args[3], (ast.List, ast.Tuple)): - for item in args[3].elts: - if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - constraint_node = item.elts[0] - value_node = item.elts[1] - if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): - input_constraints.append(constraint_node.value) - value = self.HandleExprLlvm(value_node) - if value: - input_values.append(value) - - clobbers = [] - if len(args) > 4 and isinstance(args[4], (ast.List, ast.Tuple)): - for item in args[4].elts: - if isinstance(item, ast.Constant) and isinstance(item.value, str): - clobbers.append(item.value) - - constraint_parts = [] - for oc in output_constraints: - constraint_parts.append(oc) - - input_start_idx = len(output_constraints) - for ic in input_constraints: - constraint_parts.append(ic) - - full_constraint = ",".join(constraint_parts) - - if clobbers: - if full_constraint: - full_constraint += "," - for c in clobbers: - full_constraint += f"~{{{c}}}" - - operands = output_values + input_values - param_types = [v.type for v in operands] - func_type = ir.FunctionType(output_type, param_types) - asm_dialect = self._format_to_dialect(asm_format) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, operands, name="asm_result") - return result - - return None - - def _prepare_intel_asm(self, template: str) -> str: - import re - template = re.sub(r'%(\d+)', r'$\1', template) - template = re.sub(r'%([a-zA-Z][a-zA-Z0-9]*)', r'\1', template) - return template - - def _normalize_asm_template(self, template: str) -> str: - lines = template.split('\n') - if len(lines) <= 1: - return template - first_line = lines[0] - rest_lines = lines[1:] - stripped = [] - for line in rest_lines: - s = line.lstrip() - if s: - stripped.append(s) - else: - stripped.append('') - return '\n'.join([first_line] + stripped) - - def _process_joined_str_template(self, node, out_input_ops, out_input_constraints, - out_output_ops, out_output_constraints): - if not isinstance(node, ast.JoinedStr): - if isinstance(node, ast.Constant) and isinstance(node.value, str): - return node.value - return '' - - raw_parts = [] - for value in node.values: - if isinstance(value, ast.Constant) and isinstance(value.value, str): - raw_parts.append(('text', value.value)) - elif isinstance(value, ast.FormattedValue): - expr = value.value - if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute): - if isinstance(expr.func.value, ast.Name) and expr.func.value.id == 'c': - if expr.func.attr == 'AsmInp': - if expr.args: - v = self.HandleExprLlvm(expr.args[0]) - if v: - c = 'r' - if len(expr.args) >= 2: - c = self._parse_asm_descr(expr.args[1]) - if not c: - c = 'r' - out_input_ops.append(v) - out_input_constraints.append(c) - raw_parts.append(('input', len(out_input_ops) - 1)) - elif expr.func.attr == 'AsmOut': - if expr.args: - target_ptr = self._get_var_ptr_for_asm(expr.args[0]) - if target_ptr: - v = target_ptr - else: - v = self.HandleExprLlvm(expr.args[0]) - if v: - c = '=r' - if len(expr.args) >= 2: - c = self._parse_asm_descr(expr.args[1]) - if not c: - c = '=r' - if not c.startswith('='): - c = '=' + c - out_output_ops.append(v) - out_output_constraints.append(c) - raw_parts.append(('output', len(out_output_ops) - 1)) - else: - fallback = self.HandleExprLlvm(expr) - if fallback and isinstance(fallback.type, ir.IntType): - out_input_ops.append(fallback) - out_input_constraints.append('r') - raw_parts.append(('input', len(out_input_ops) - 1)) - else: - raw_parts.append(('text', '')) - - num_outputs = len(out_output_ops) - parts = [] - for kind, data in raw_parts: - if kind == 'text': - parts.append(data) - elif kind == 'output': - parts.append(f'%{data}') - elif kind == 'input': - parts.append(f'%{num_outputs + data}') - return ''.join(parts) - - _X86_REGISTERS = frozenset({ - 'rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', - 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', - 'eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp', - 'ax', 'bx', 'cx', 'dx', 'si', 'di', 'bp', 'sp', - 'al', 'bl', 'cl', 'dl', 'ah', 'bh', 'ch', 'dh', - 'sil', 'dil', 'bpl', 'spl', - 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d', - 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w', - 'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b', - }) - - def _mangle_asm_calls(self, template: str) -> str: - import re - Gen = self.Trans.LlvmGen - sha1 = getattr(Gen, 'module_sha1', '') - if not sha1: - return template - - def replace_call(m): - prefix = m.group(1) - func_name = m.group(2) - if func_name.lower() in self._X86_REGISTERS: - return m.group(0) - mangled = Gen._mangle_func_name(func_name) - 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, op_arg, input_arg=None, output_arg=None, asm_format='Intel'): - Gen = self.Trans.LlvmGen - - input_ops = [] - input_constraints = [] - output_ops = [] - output_constraints = [] - - if output_arg and isinstance(output_arg, (ast.List, ast.Tuple)): - for item in output_arg.elts: - if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): - if item.func.value.id == 'c' and item.func.attr == 'AsmOut': - if len(item.args) >= 1: - target_ptr = self._get_var_ptr_for_asm(item.args[0]) - if target_ptr: - output_ops.append(target_ptr) - else: - value = self.HandleExprLlvm(item.args[0]) - if value: - output_ops.append(value) - constraint = '=r' - if len(item.args) >= 2: - base_constraint = self._parse_asm_descr(item.args[1]) - if base_constraint: - if base_constraint.startswith('='): - constraint = base_constraint - else: - constraint = '=' + base_constraint - output_constraints.append(constraint) - - if isinstance(asm_template_arg, ast.JoinedStr): - raw_template = self._normalize_asm_template( - self._process_joined_str_template( - asm_template_arg, input_ops, input_constraints, output_ops, output_constraints - ) - ) - elif isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): - raw_template = self._normalize_asm_template(asm_template_arg.value) - else: - raw_template = '' - - raw_template = self._mangle_asm_calls(raw_template) - asm_dialect = self._format_to_dialect(asm_format) - if asm_format == 'AT&T': - asm_template = raw_template # AT&T 不需要转换 - elif asm_format == 'ARM': - asm_template = raw_template # ARM 不需要转换 - else: - asm_template = self._prepare_intel_asm(raw_template) # Intel → LLVM IR 格式 - - if input_arg and isinstance(input_arg, (ast.List, ast.Tuple)): - for item in input_arg.elts: - if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): - if item.func.value.id == 'c' and item.func.attr == 'AsmInp': - if len(item.args) >= 1: - value = self.HandleExprLlvm(item.args[0]) - if value: - input_ops.append(value) - constraint = 'r' - if len(item.args) >= 2: - constraint = self._parse_asm_descr(item.args[1]) - if not constraint: - constraint = 'r' - input_constraints.append(constraint) - elif isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - value_node = item.elts[0] - descr_node = item.elts[1] - value = self.HandleExprLlvm(value_node) - if value: - input_ops.append(value) - constraint = self._parse_asm_descr(descr_node) - if not constraint: - constraint = 'r' - input_constraints.append(constraint) - - clobbers = [] - if op_arg and isinstance(op_arg, (ast.List, ast.Tuple)): - for item in op_arg.elts: - clobber = self._parse_asm_descr(item) - if clobber: - clobbers.append(clobber) - - constraint_parts = [] - for oc in output_constraints: - c = oc if oc.startswith('=') else ('=' + oc) - constraint_parts.append(c) - for ic in input_constraints: - if ic in ('d', 'edx', 'rdx'): - constraint_parts.append('{dx}') - else: - constraint_parts.append(ic) - - full_constraint = ",".join(constraint_parts) - - constraint_to_reg = { - 'a': 'rax', 'b': 'rbx', 'c': 'rcx', 'd': 'rdx', - 'S': 'rsi', 'D': 'rdi', - 'A': 'rax', 'U': 'r8', - } - used_regs = set() - for ic in input_constraints: - if ic in constraint_to_reg: - used_regs.add(constraint_to_reg[ic]) - for oc in output_constraints: - base_oc = oc.lstrip('=').lstrip('+') - if base_oc in constraint_to_reg: - used_regs.add(constraint_to_reg[base_oc]) - - if clobbers: - has_memory = 'memory' in clobbers - if has_memory and output_ops: - clobbers = [c for c in clobbers if c != 'memory'] - if asm_format == 'ARM': - # ARM 不需要 x86 的 e→r 寄存器名转换 - clobber_final = [c for c in clobbers if c not in used_regs] - else: - clobber_64bit = [] - for c in clobbers: - if c in ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp']: - clobber_64bit.append(c.replace('e', 'r')) - else: - clobber_64bit.append(c) - clobber_final = [c for c in clobber_64bit if c not in used_regs] - if clobber_final: - if full_constraint: - full_constraint += "," - full_constraint += ",".join([f"~{{{c}}}" for c in clobber_final]) - - if output_ops: - single_out = len(output_ops) == 1 - if single_out: - op = output_ops[0] - if isinstance(op, ir.AllocaInstr): - ret_type = op.type.pointee - elif isinstance(op, ir.GlobalVariable): - ret_type = op.type.pointee - elif isinstance(op, (ir.GEPInstr, ir.CastInstr)): - ret_type = op.type.pointee if isinstance(op.type, ir.PointerType) else op.type - else: - ret_type = op.type - else: - def _get_ret_type(op): - if isinstance(op, (ir.AllocaInstr, ir.GlobalVariable)): - return op.type.pointee - return op.type - ret_type = ir.LiteralStructType([_get_ret_type(op) for op in output_ops]) - if isinstance(ret_type, ir.PointerType) and isinstance(ret_type.pointee, ir.IdentifiedStructType): - ret_type = ir.IntType(64) - operands = input_ops - param_types = [op.type for op in operands] - func_type = ir.FunctionType(ret_type, param_types) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, operands, name="asm_result") - if single_out: - target = output_ops[0] - if isinstance(target, ir.AllocaInstr): - if target.type.pointee != result.type: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(result, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) - Gen.builder.store(iv, ptr) - else: - Gen.builder.store(result, target) - elif isinstance(target, (ir.GlobalVariable, ir.GEPInstr, ir.CastInstr)): - target_pointee = target.type.pointee - if target_pointee != result.type: - if isinstance(target_pointee, ir.PointerType) and isinstance(result, ir.Instruction) and result.type == ir.IntType(64): - ptr_val = Gen.builder.inttoptr(result, target_pointee) - Gen.builder.store(ptr_val, target) - else: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(result, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) - Gen.builder.store(iv, ptr) - else: - Gen.builder.store(result, target) - else: - dst = Gen._alloca_entry(result.type) - Gen.builder.store(result, dst) - else: - for i, out_op in enumerate(output_ops): - val = Gen.builder.extract_value(result, i, name=f"asm_out_{i}") - target = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._alloca_entry(val.type) - if isinstance(target, ir.AllocaInstr) and target.type.pointee != val.type: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(val, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) - Gen.builder.store(iv, ptr) - else: - Gen.builder.store(val, target) - else: - operands = input_ops - param_types = [op.type for op in operands] - func_type = ir.FunctionType(ir.VoidType(), param_types) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect) - Gen.builder.call(inline_asm, operands, name="asm_call") - return ir.Constant(ir.IntType(32), 1) - - def _get_var_ptr_for_asm(self, node): - Gen = self.Trans.LlvmGen - if isinstance(node, ast.Name): - var_name = node.id - if var_name in Gen.variables and Gen.variables[var_name] is not None: - ptr = Gen.variables[var_name] - if isinstance(ptr, ir.AllocaInstr): - return ptr - if isinstance(ptr, ir.GlobalVariable): - return ptr - elif isinstance(node, ast.Attribute): - obj_ptr = self._get_var_ptr_for_asm(node.value) - if obj_ptr is not None: - obj_type = obj_ptr.type.pointee - if isinstance(obj_type, ir.PointerType) and isinstance(obj_type.pointee, ir.IdentifiedStructType): - loaded = Gen.builder.load(obj_ptr, name="asm_attr_load") - struct_type = obj_type.pointee - class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None - if class_name: - offset = Gen._get_member_offset(node.attr, class_name) - gep = Gen.builder.gep(loaded, [ir.Constant(ir.IntType(32), 0), - ir.Constant(ir.IntType(32), offset)], - inbounds=True) - return gep - for idx, elem_type in enumerate(struct_type.elements): - gep = Gen.builder.gep(loaded, [ir.Constant(ir.IntType(32), 0), - ir.Constant(ir.IntType(32), idx)], - inbounds=True) - return gep - elif isinstance(obj_type, ir.IdentifiedStructType): - class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None - if class_name: - offset = Gen._get_member_offset(node.attr, class_name) - gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), - ir.Constant(ir.IntType(32), offset)], - inbounds=True) - return gep - for idx, elem_type in enumerate(obj_type.elements): - gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), - ir.Constant(ir.IntType(32), idx)], - inbounds=True) - return gep - return None - - def _parse_asm_descr(self, expr): - from lib.includes import t - - if isinstance(expr, ast.BinOp): - left_val = self._parse_asm_descr(expr.left) - right_val = self._parse_asm_descr(expr.right) - return left_val + right_val - - elif isinstance(expr, ast.Attribute): - if isinstance(expr.value, ast.Attribute): - if (isinstance(expr.value.value, ast.Name) and - expr.value.value.id == 't' and - expr.value.attr == 'ASM_DESCR'): - AttrName = expr.attr - return getattr(t.ASM_DESCR, AttrName, "") - elif isinstance(expr.value, ast.Name) and expr.value.id == 't': - AttrName = expr.attr - return getattr(t.ASM_DESCR, AttrName, "") - - elif isinstance(expr, ast.Constant): - return expr.value - - return "" - - def _infer_expr_llvm_type(self, expr): - import llvmlite.ir as ir - if isinstance(expr, ast.Name): - type_name = expr.id - if hasattr(t, type_name): - ctype = getattr(t, type_name) - if isinstance(ctype, type) and issubclass(ctype, t.CType): - size = getattr(ctype, 'Size', None) - if size is not None: - return ir.IntType(size) - if type_name == 'CFloat': - return ir.FloatType() - elif type_name == 'CDouble': - return ir.DoubleType() - elif isinstance(expr, ast.Attribute): - if isinstance(expr.value, ast.Name) and expr.value.id == 't': - return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load())) - return None +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 ast +import llvmlite.ir as ir +import t + +# 猴子补丁 llvmlite.ir.InlineAsm 以支持 asm_dialect 参数 +# 添加保护避免重复补丁 +_InlineAsmPatched = getattr(ir.InlineAsm, '_transpyc_patched', False) + +if not _InlineAsmPatched: + _OrigInlineAsmInit = ir.InlineAsm.__init__ + _OrigInlineAsmDescr = ir.InlineAsm.descr + + def _patched_inline_asm_init(self, ftype, asm, constraint, side_effect=False, asm_dialect=None): + _OrigInlineAsmInit(self, ftype, asm, constraint, side_effect) + self.asm_dialect = asm_dialect + + def _patched_inline_asm_descr(self, buf): + sideeffect = 'sideeffect' if self.side_effect else '' + dialect_str = getattr(self, 'asm_dialect', None) + if dialect_str == 'intel': + dialect = 'inteldialect' + else: + dialect = '' + fmt = 'asm {sideeffect} {dialect} "{asm}", "{constraint}"' + buf.append(fmt.format(sideeffect=sideeffect, dialect=dialect, asm=self.asm, + constraint=self.constraint)) + + ir.InlineAsm.__init__ = _patched_inline_asm_init + ir.InlineAsm.descr = _patched_inline_asm_descr + ir.InlineAsm._transpyc_patched = True + + +class ExprAsmHandle(BaseHandle): + @staticmethod + def _format_to_dialect(asm_format): + """将用户指定的 format 参数转换为 LLVM asm_dialect 值""" + fmt = asm_format.lower() if asm_format else 'intel' + if fmt == 'att': + return 'att' + elif fmt == 'arm': + return None # ARM 没有专门的 dialect 标记 + else: + return 'intel' # 默认 Intel + + def _HandleAsmLlvm(self, Node): + Gen = self.Trans.LlvmGen + + op_arg = None + input_arg = None + output_arg = None + asm_format = 'Intel' # 汇编格式: Intel / AT&T / ARM + for kw in Node.keywords: + if kw.arg == 'op': + op_arg = kw.value + elif kw.arg in ('input', 'inp', 'inputs'): + input_arg = kw.value + elif kw.arg in ('output', 'out', 'outputs'): + output_arg = kw.value + elif kw.arg == 'format': + if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str): + asm_format = kw.value.value + + if len(Node.args) >= 1: + pos_op = None + if len(Node.args) >= 2 and op_arg is None: + pos_op = Node.args[1] + return self._HandleAsmWithOpLlvm(Node.args[0], op_arg or pos_op, input_arg, output_arg, asm_format) + + if len(Node.args) < 2: + return ir.Constant(ir.IntType(32), 1) + + args = Node.args + + if len(args) == 4: + output_type_arg = args[0] + asm_template_arg = args[1] + constraint_arg = args[2] + clobber_arg = args[3] + + output_type = self._infer_expr_llvm_type(output_type_arg) + if not output_type: + output_type = ir.IntType(32) + + asm_template = '' + if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): + asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) + + constraint = '' + if isinstance(constraint_arg, ast.Constant) and isinstance(constraint_arg.value, str): + constraint = constraint_arg.value + + clobber = '' + if isinstance(clobber_arg, ast.Constant) and isinstance(clobber_arg.value, str): + clobber = clobber_arg.value + + full_constraint = constraint + func_type = ir.FunctionType(output_type, []) + asm_dialect = self._format_to_dialect(asm_format) + inline_asm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect) + result = Gen.builder.call(inline_asm, [], name="asm_result") + return result + + elif len(args) >= 2: + output_type_arg = args[0] + asm_template_arg = args[1] + + output_type = self._infer_expr_llvm_type(output_type_arg) + if not output_type: + output_type = ir.IntType(32) + + asm_template = '' + if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): + asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) + + output_constraints = [] + output_values = [] + if len(args) > 2 and isinstance(args[2], (ast.List, ast.Tuple)): + for item in args[2].elts: + if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: + constraint_node = item.elts[0] + value_node = item.elts[1] + if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): + output_constraints.append(constraint_node.value) + value = self.HandleExprLlvm(value_node) + if value: + output_values.append(value) + + input_constraints = [] + input_values = [] + if len(args) > 3 and isinstance(args[3], (ast.List, ast.Tuple)): + for item in args[3].elts: + if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: + constraint_node = item.elts[0] + value_node = item.elts[1] + if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): + input_constraints.append(constraint_node.value) + value = self.HandleExprLlvm(value_node) + if value: + input_values.append(value) + + clobbers = [] + if len(args) > 4 and isinstance(args[4], (ast.List, ast.Tuple)): + for item in args[4].elts: + if isinstance(item, ast.Constant) and isinstance(item.value, str): + clobbers.append(item.value) + + constraint_parts = [] + for oc in output_constraints: + constraint_parts.append(oc) + + input_start_idx = len(output_constraints) + for ic in input_constraints: + constraint_parts.append(ic) + + full_constraint = ",".join(constraint_parts) + + if clobbers: + if full_constraint: + full_constraint += "," + for c in clobbers: + full_constraint += f"~{{{c}}}" + + operands = output_values + input_values + param_types = [v.type for v in operands] + func_type = ir.FunctionType(output_type, param_types) + asm_dialect = self._format_to_dialect(asm_format) + inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect) + result = Gen.builder.call(inline_asm, operands, name="asm_result") + return result + + return None + + def _prepare_intel_asm(self, template: str) -> str: + import re + template = re.sub(r'%(\d+)', r'$\1', template) + template = re.sub(r'%([a-zA-Z][a-zA-Z0-9]*)', r'\1', template) + return template + + def _normalize_asm_template(self, template: str) -> str: + lines = template.split('\n') + if len(lines) <= 1: + return template + first_line = lines[0] + rest_lines = lines[1:] + stripped = [] + for line in rest_lines: + s = line.lstrip() + if s: + stripped.append(s) + else: + stripped.append('') + return '\n'.join([first_line] + stripped) + + def _process_joined_str_template(self, node, out_input_ops, out_input_constraints, + out_output_ops, out_output_constraints): + if not isinstance(node, ast.JoinedStr): + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value + return '' + + raw_parts = [] + for value in node.values: + if isinstance(value, ast.Constant) and isinstance(value.value, str): + raw_parts.append(('text', value.value)) + elif isinstance(value, ast.FormattedValue): + expr = value.value + if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute): + if isinstance(expr.func.value, ast.Name) and expr.func.value.id == 'c': + if expr.func.attr == 'AsmInp': + if expr.args: + v = self.HandleExprLlvm(expr.args[0]) + if v: + c = 'r' + if len(expr.args) >= 2: + c = self._parse_asm_descr(expr.args[1]) + if not c: + c = 'r' + out_input_ops.append(v) + out_input_constraints.append(c) + raw_parts.append(('input', len(out_input_ops) - 1)) + elif expr.func.attr == 'AsmOut': + if expr.args: + target_ptr = self._get_var_ptr_for_asm(expr.args[0]) + if target_ptr: + v = target_ptr + else: + v = self.HandleExprLlvm(expr.args[0]) + if v: + c = '=r' + if len(expr.args) >= 2: + c = self._parse_asm_descr(expr.args[1]) + if not c: + c = '=r' + if not c.startswith('='): + c = '=' + c + out_output_ops.append(v) + out_output_constraints.append(c) + raw_parts.append(('output', len(out_output_ops) - 1)) + else: + fallback = self.HandleExprLlvm(expr) + if fallback and isinstance(fallback.type, ir.IntType): + out_input_ops.append(fallback) + out_input_constraints.append('r') + raw_parts.append(('input', len(out_input_ops) - 1)) + else: + raw_parts.append(('text', '')) + + num_outputs = len(out_output_ops) + parts = [] + for kind, data in raw_parts: + if kind == 'text': + parts.append(data) + elif kind == 'output': + parts.append(f'%{data}') + elif kind == 'input': + parts.append(f'%{num_outputs + data}') + return ''.join(parts) + + _X86_REGISTERS = frozenset({ + 'rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', + 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', + 'eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp', + 'ax', 'bx', 'cx', 'dx', 'si', 'di', 'bp', 'sp', + 'al', 'bl', 'cl', 'dl', 'ah', 'bh', 'ch', 'dh', + 'sil', 'dil', 'bpl', 'spl', + 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d', + 'r8w', 'r9w', 'r10w', 'r11w', 'r12w', 'r13w', 'r14w', 'r15w', + 'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b', + }) + + def _mangle_asm_calls(self, template: str) -> str: + import re + Gen = self.Trans.LlvmGen + sha1 = getattr(Gen, 'module_sha1', '') + if not sha1: + return template + + def replace_call(m): + prefix = m.group(1) + func_name = m.group(2) + if func_name.lower() in self._X86_REGISTERS: + return m.group(0) + mangled = Gen._mangle_func_name(func_name) + 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, op_arg, input_arg=None, output_arg=None, asm_format='Intel'): + Gen = self.Trans.LlvmGen + + input_ops = [] + input_constraints = [] + output_ops = [] + output_constraints = [] + + if output_arg and isinstance(output_arg, (ast.List, ast.Tuple)): + for item in output_arg.elts: + if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): + if item.func.value.id == 'c' and item.func.attr == 'AsmOut': + if len(item.args) >= 1: + target_ptr = self._get_var_ptr_for_asm(item.args[0]) + if target_ptr: + output_ops.append(target_ptr) + else: + value = self.HandleExprLlvm(item.args[0]) + if value: + output_ops.append(value) + constraint = '=r' + if len(item.args) >= 2: + base_constraint = self._parse_asm_descr(item.args[1]) + if base_constraint: + if base_constraint.startswith('='): + constraint = base_constraint + else: + constraint = '=' + base_constraint + output_constraints.append(constraint) + + if isinstance(asm_template_arg, ast.JoinedStr): + raw_template = self._normalize_asm_template( + self._process_joined_str_template( + asm_template_arg, input_ops, input_constraints, output_ops, output_constraints + ) + ) + elif isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): + raw_template = self._normalize_asm_template(asm_template_arg.value) + else: + raw_template = '' + + raw_template = self._mangle_asm_calls(raw_template) + asm_dialect = self._format_to_dialect(asm_format) + if asm_format == 'AT&T': + asm_template = raw_template # AT&T 不需要转换 + elif asm_format == 'ARM': + asm_template = raw_template # ARM 不需要转换 + else: + asm_template = self._prepare_intel_asm(raw_template) # Intel → LLVM IR 格式 + + if input_arg and isinstance(input_arg, (ast.List, ast.Tuple)): + for item in input_arg.elts: + if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): + if item.func.value.id == 'c' and item.func.attr == 'AsmInp': + if len(item.args) >= 1: + value = self.HandleExprLlvm(item.args[0]) + if value: + input_ops.append(value) + constraint = 'r' + if len(item.args) >= 2: + constraint = self._parse_asm_descr(item.args[1]) + if not constraint: + constraint = 'r' + input_constraints.append(constraint) + elif isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: + value_node = item.elts[0] + descr_node = item.elts[1] + value = self.HandleExprLlvm(value_node) + if value: + input_ops.append(value) + constraint = self._parse_asm_descr(descr_node) + if not constraint: + constraint = 'r' + input_constraints.append(constraint) + + clobbers = [] + if op_arg and isinstance(op_arg, (ast.List, ast.Tuple)): + for item in op_arg.elts: + clobber = self._parse_asm_descr(item) + if clobber: + clobbers.append(clobber) + + constraint_parts = [] + for oc in output_constraints: + c = oc if oc.startswith('=') else ('=' + oc) + constraint_parts.append(c) + for ic in input_constraints: + if ic in ('d', 'edx', 'rdx'): + constraint_parts.append('{dx}') + else: + constraint_parts.append(ic) + + full_constraint = ",".join(constraint_parts) + + constraint_to_reg = { + 'a': 'rax', 'b': 'rbx', 'c': 'rcx', 'd': 'rdx', + 'S': 'rsi', 'D': 'rdi', + 'A': 'rax', 'U': 'r8', + } + used_regs = set() + for ic in input_constraints: + if ic in constraint_to_reg: + used_regs.add(constraint_to_reg[ic]) + for oc in output_constraints: + base_oc = oc.lstrip('=').lstrip('+') + if base_oc in constraint_to_reg: + used_regs.add(constraint_to_reg[base_oc]) + + if clobbers: + has_memory = 'memory' in clobbers + if has_memory and output_ops: + clobbers = [c for c in clobbers if c != 'memory'] + if asm_format == 'ARM': + # ARM 不需要 x86 的 e→r 寄存器名转换 + clobber_final = [c for c in clobbers if c not in used_regs] + else: + clobber_64bit = [] + for c in clobbers: + if c in ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp']: + clobber_64bit.append(c.replace('e', 'r')) + else: + clobber_64bit.append(c) + clobber_final = [c for c in clobber_64bit if c not in used_regs] + if clobber_final: + if full_constraint: + full_constraint += "," + full_constraint += ",".join([f"~{{{c}}}" for c in clobber_final]) + + if output_ops: + single_out = len(output_ops) == 1 + if single_out: + op = output_ops[0] + if isinstance(op, ir.AllocaInstr): + ret_type = op.type.pointee + elif isinstance(op, ir.GlobalVariable): + ret_type = op.type.pointee + elif isinstance(op, (ir.GEPInstr, ir.CastInstr)): + ret_type = op.type.pointee if isinstance(op.type, ir.PointerType) else op.type + else: + ret_type = op.type + else: + def _get_ret_type(op): + if isinstance(op, (ir.AllocaInstr, ir.GlobalVariable)): + return op.type.pointee + return op.type + ret_type = ir.LiteralStructType([_get_ret_type(op) for op in output_ops]) + if isinstance(ret_type, ir.PointerType) and isinstance(ret_type.pointee, ir.IdentifiedStructType): + ret_type = ir.IntType(64) + operands = input_ops + param_types = [op.type for op in operands] + func_type = ir.FunctionType(ret_type, param_types) + inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect) + result = Gen.builder.call(inline_asm, operands, name="asm_result") + if single_out: + target = output_ops[0] + if isinstance(target, ir.AllocaInstr): + if target.type.pointee != result.type: + i64t = ir.IntType(64) + iv = Gen.builder.ptrtoint(result, i64t) + ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + Gen.builder.store(iv, ptr) + else: + Gen.builder.store(result, target) + elif isinstance(target, (ir.GlobalVariable, ir.GEPInstr, ir.CastInstr)): + target_pointee = target.type.pointee + if target_pointee != result.type: + if isinstance(target_pointee, ir.PointerType) and isinstance(result, ir.Instruction) and result.type == ir.IntType(64): + ptr_val = Gen.builder.inttoptr(result, target_pointee) + Gen.builder.store(ptr_val, target) + else: + i64t = ir.IntType(64) + iv = Gen.builder.ptrtoint(result, i64t) + ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + Gen.builder.store(iv, ptr) + else: + Gen.builder.store(result, target) + else: + dst = Gen._allocaEntry(result.type) + Gen.builder.store(result, dst) + else: + for i, out_op in enumerate(output_ops): + val = Gen.builder.extract_value(result, i, name=f"asm_out_{i}") + target = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._allocaEntry(val.type) + if isinstance(target, ir.AllocaInstr) and target.type.pointee != val.type: + i64t = ir.IntType(64) + iv = Gen.builder.ptrtoint(val, i64t) + ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + Gen.builder.store(iv, ptr) + else: + Gen.builder.store(val, target) + else: + operands = input_ops + param_types = [op.type for op in operands] + func_type = ir.FunctionType(ir.VoidType(), param_types) + inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect) + Gen.builder.call(inline_asm, operands, name="asm_call") + return ir.Constant(ir.IntType(32), 1) + + def _get_var_ptr_for_asm(self, node): + Gen = self.Trans.LlvmGen + if isinstance(node, ast.Name): + var_name = node.id + if var_name in Gen.variables and Gen.variables[var_name] is not None: + ptr = Gen.variables[var_name] + if isinstance(ptr, ir.AllocaInstr): + return ptr + if isinstance(ptr, ir.GlobalVariable): + return ptr + elif isinstance(node, ast.Attribute): + obj_ptr = self._get_var_ptr_for_asm(node.value) + if obj_ptr is not None: + obj_type = obj_ptr.type.pointee + if isinstance(obj_type, ir.PointerType) and isinstance(obj_type.pointee, ir.IdentifiedStructType): + Loaded = Gen.builder.load(obj_ptr, name="asm_attr_Load") + struct_type = obj_type.pointee + class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None + if class_name: + offset = Gen._get_member_offset(node.attr, class_name) + gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), + ir.Constant(ir.IntType(32), offset)], + inbounds=True) + return gep + for idx, elem_type in enumerate(struct_type.elements): + gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), + ir.Constant(ir.IntType(32), idx)], + inbounds=True) + return gep + elif isinstance(obj_type, ir.IdentifiedStructType): + class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None + if class_name: + offset = Gen._get_member_offset(node.attr, class_name) + gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), + ir.Constant(ir.IntType(32), offset)], + inbounds=True) + return gep + for idx, elem_type in enumerate(obj_type.elements): + gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), + ir.Constant(ir.IntType(32), idx)], + inbounds=True) + return gep + return None + + def _parse_asm_descr(self, expr): + from lib.includes import t + + if isinstance(expr, ast.BinOp): + left_val = self._parse_asm_descr(expr.left) + right_val = self._parse_asm_descr(expr.right) + return left_val + right_val + + elif isinstance(expr, ast.Attribute): + if isinstance(expr.value, ast.Attribute): + if (isinstance(expr.value.value, ast.Name) and + expr.value.value.id == 't' and + expr.value.attr == 'ASM_DESCR'): + AttrName = expr.attr + return getattr(t.ASM_DESCR, AttrName, "") + elif isinstance(expr.value, ast.Name) and expr.value.id == 't': + AttrName = expr.attr + return getattr(t.ASM_DESCR, AttrName, "") + + elif isinstance(expr, ast.Constant): + return expr.value + + return "" + + def _infer_expr_llvm_type(self, expr): + import llvmlite.ir as ir + if isinstance(expr, ast.Name): + type_name = expr.id + if hasattr(t, type_name): + ctype = getattr(t, type_name) + if isinstance(ctype, type) and issubclass(ctype, t.CType): + size = getattr(ctype, 'Size', None) + if size is not None: + return ir.IntType(size) + if type_name == 'CFloat': + return ir.FloatType() + elif type_name == 'CDouble': + return ir.DoubleType() + elif isinstance(expr, ast.Attribute): + if isinstance(expr.value, ast.Name) and expr.value.id == 't': + return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load())) + return None diff --git a/lib/core/Handles/HandlesExprAttr.py b/lib/core/Handles/HandlesExprAttr.py index b476008..2a29cce 100644 --- a/lib/core/Handles/HandlesExprAttr.py +++ b/lib/core/Handles/HandlesExprAttr.py @@ -1,1161 +1,1161 @@ -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, FuncMeta -import ast -import llvmlite.ir as ir - - -class ExprAttrHandle(BaseHandle): - - # ========== 辅助方法 ========== - - def _apply_bswap_on_load(self, val, ClassName, AttrName): - Gen = self.Trans.LlvmGen - byte_order = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") - if byte_order == 'big' and isinstance(val.type, ir.IntType): - if val.type.width in (16, 32, 64): - val = Gen.builder.bswap(val, name=f"bswap_load_{AttrName}") - return val - - def _gep_and_load_member(self, Gen, ObjVal, offset, AttrName, ClassName, ST=None): - """从结构体指针通过 GEP 取成员,处理 array/struct pointer/class_members 特殊情况""" - if offset is None: - return None - if isinstance(ObjVal.type, ir.PointerType): - pointee = ObjVal.type.pointee - if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is not None and offset >= len(pointee.elements): - return None - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.ArrayType): - return MemberPtr - if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.IdentifiedStructType): - return MemberPtr - # 检查 pointer-to-pointer 且实际元素是 ArrayType - if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.PointerType): - actual_elem_type = None - if ST is not None and isinstance(ST, ir.IdentifiedStructType) and ST.elements is not None and offset < len(ST.elements): - actual_elem_type = ST.elements[offset] - if isinstance(actual_elem_type, ir.ArrayType): - return Gen.builder.bitcast(MemberPtr, ir.PointerType(actual_elem_type), name=f"cast_arr_{AttrName}") - # 检查 class_members 中的 ArrayType - if ClassName in Gen.class_members: - for member_name, member_type in Gen.class_members[ClassName]: - if member_name == AttrName and isinstance(member_type, ir.ArrayType): - return Gen.builder.bitcast(MemberPtr, ir.PointerType(member_type), name=f"cast_arr_{AttrName}") - val = Gen._load(MemberPtr, name=AttrName) - return self._apply_bswap_on_load(val, ClassName, AttrName) - - def _try_load_struct_from_stub(self, Gen, ClassName): - """尝试从 stub 加载结构体定义,返回 (struct_type, ok)""" - if ClassName not in Gen.structs: - return None, False - st = Gen.structs[ClassName] - if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) - st = Gen.structs.get(ClassName, st) - if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): - return st, False - return st, True - - def _make_define_constant(self, Gen, val): - """将 CDefine 值转为 LLVM 常量""" - if isinstance(val, int): - if abs(val) > 2147483647: - return ir.Constant(ir.IntType(64), val) - return ir.Constant(ir.IntType(32), val) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - 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 - return Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return None - - def _lookup_cdefine(self, Gen, VarName, AttrName): - """在符号表和模块中查找 CDefine 常量值""" - imported_modules = getattr(self.Trans, '_imported_modules', None) - if not imported_modules: - return None - PossibleKeys = [f"{VarName}.{AttrName}", AttrName] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - key = f"{mod_name}.{AttrName}" - if key not in PossibleKeys: - PossibleKeys.append(key) - for lookup_key in PossibleKeys: - SymInfo = self.Trans.SymbolTable.get(lookup_key) - if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: - return self._make_define_constant(Gen, SymInfo.DefineValue) - # 也检查 _define_constants - define_constants = getattr(Gen, '_define_constants', {}) - for key in (f"{VarName}.{AttrName}", AttrName): - if key in define_constants: - return self._make_define_constant(Gen, define_constants[key]) - return None - - def _lookup_module_global(self, Gen, VarName, AttrName): - """在模块全局变量中查找 import 的属性""" - imported_modules = getattr(self.Trans, '_imported_modules', None) - import_aliases = getattr(self.Trans, '_import_aliases', {}) - if not imported_modules: - return None - resolved_mod = import_aliases.get(VarName, VarName) - if VarName not in imported_modules and resolved_mod not in imported_modules: - return None - PossibleKeys = [f"{VarName}.{AttrName}", AttrName] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - key = f"{mod_name}.{AttrName}" - if key not in PossibleKeys: - PossibleKeys.append(key) - for key in PossibleKeys: - if key in Gen.module.globals: - GVar = Gen.module.globals[key] - 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=AttrName) - # SHA1 前缀查找 - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - sha1_candidates = [VarName, resolved_mod] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - if mod_name not in sha1_candidates: - sha1_candidates.append(mod_name) - for cand in sha1_candidates: - sha1 = module_sha1_map.get(cand) - if sha1: - prefixed = f"{sha1}.{AttrName}" - if prefixed in Gen.module.globals: - GVar2 = Gen.module.globals[prefixed] - if isinstance(GVar2, ir.Function): - return GVar2 - if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar2 - return Gen._load(GVar2, name=AttrName) - if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] - if AttrName in Gen.variables and Gen.variables[AttrName] is None: - str_gv_name = AttrName + '_str' - if str_gv_name in Gen.module.globals: - str_gv = Gen.module.globals[str_gv_name] - return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") - return Gen.builder.load(gv, name=AttrName) - return None - - def _resolve_var_classname(self, Gen, VarName): - """根据变量名解析其结构体类名""" - ClassName = Gen.var_struct_class.get(VarName) - if not ClassName and getattr(Gen, 'global_struct_class', None): - ClassName = Gen.global_struct_class.get(VarName) - if ClassName: - Gen.var_struct_class[VarName] = ClassName - if not ClassName and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(GVar.type.pointee) - if found: - ClassName = found[0] - Gen.var_struct_class[VarName] = ClassName - if getattr(Gen, 'global_struct_class', None): - Gen.global_struct_class[VarName] = ClassName - if not ClassName and VarName in Gen.variables: - VarPtr = Gen.variables[VarName] - if VarPtr is not None and isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee - if isinstance(pointee, ir.PointerType): - pointee = pointee.pointee - found = Gen.find_struct_by_pointee(pointee) - if found: - ClassName = found[0] - return ClassName - - def _check_struct_match(self, Gen, ObjVal, ClassName): - """检查 ObjVal 是否指向 ClassName 对应的结构体""" - if ClassName not in Gen.structs: - return False - if isinstance(ObjVal.type, ir.PointerType): - ST = Gen.structs[ClassName] - if ObjVal.type.pointee == ST: - return True - if isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and ObjVal.type.pointee.name == ST.name: - return True - return False - - # ========== _HandleAttributeLlvm 子方法 ========== - - def _handle_attr_self(self, Node, VarName): - """处理 self.xxx 属性访问""" - Gen = self.Trans.LlvmGen - ClassName = self.Trans._CurrentCpythonObjectClass - if not ClassName: - return None - # 检查 property getter - PropKey = f'{ClassName}.{Node.attr}' - PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: - SelfVar = Gen._get_var_ptr('self') - if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - GetterFunc = Gen._get_function(PropKey) - if GetterFunc and SelfPtr: - return Gen.builder.call(GetterFunc, [SelfPtr], name=f"prop_{PropKey}") - offset = Gen._get_member_offset(Node.attr, ClassName) - SelfVar = Gen._get_var_ptr('self') - if not SelfVar: - return None - SelfPtr = Gen._load(SelfVar, name="self") - if not isinstance(SelfPtr.type, ir.PointerType): - return None - pointee = SelfPtr.type.pointee - if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: - for CN2, ST2 in Gen.structs.items(): - if isinstance(ST2, ir.IdentifiedStructType) and ST2.name == pointee.name and ST2.elements is not None: - pointee = ST2 - break - if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is not None and offset is not None and offset < len(pointee.elements): - if isinstance(pointee.elements[offset], ir.VoidType): - return None - return self._gep_and_load_member(Gen, SelfPtr, offset, Node.attr, ClassName, pointee) - DynamicVarName = f"self.{Node.attr}" - if DynamicVarName in Gen.variables: - return Gen._load(Gen.variables[DynamicVarName], name=Node.attr) - return None - - def _handle_attr_enum(self, Node, VarName): - """处理枚举成员访问 (VarName 是枚举类型名)""" - SymInfo = self.Trans.SymbolTable.get(VarName) - if not SymInfo or not getattr(SymInfo, 'IsEnum', None): - return None - if Node.attr in self.Trans.SymbolTable: - MemberInfo = self.Trans.SymbolTable[Node.attr] - if getattr(MemberInfo, 'IsEnumMember', None) and getattr(MemberInfo, 'EnumName', None) == VarName: - if isinstance(getattr(MemberInfo, 'value', None), int): - return ir.Constant(ir.IntType(32), MemberInfo.value) - for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == VarName and key == Node.attr: - if isinstance(getattr(info, 'value', None), int): - return ir.Constant(ir.IntType(32), info.value) - return None - - def _handle_attr_name(self, Node, VarName): - """处理 x.attr 形式 (x 是普通 Name)""" - Gen = self.Trans.LlvmGen - AttrName = Node.attr - - # 先尝试枚举成员 - result = self._handle_attr_enum(Node, VarName) - if result is not None: - return result - - # 尝试 CDefine 常量 - result = self._lookup_cdefine(Gen, VarName, AttrName) - if result is not None: - return result - - # 尝试 import 模块全局变量 - result = self._lookup_module_global(Gen, VarName, AttrName) - if result is not None: - return result - - # 尝试 attr 直接作为全局变量 - if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] - if AttrName in Gen.variables and Gen.variables[AttrName] is None: - str_gv_name = AttrName + '_str' - if str_gv_name in Gen.module.globals: - str_gv = Gen.module.globals[str_gv_name] - return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") - return Gen.builder.load(gv, name=AttrName) - - # 解析结构体类名并访问成员 - ClassName = self._resolve_var_classname(Gen, VarName) - if not ClassName: - return None - - # 检查 property getter - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: - ObjVal = self.HandleExprLlvm(Node.value) - GetterFunc = Gen._get_function(PropKey) - if GetterFunc and ObjVal: - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - return Gen.builder.call(GetterFunc, [ObjVal], name=f"prop_{PropKey}") - - # 获取类型信息 - TypeInfo = self.Trans.SymbolTable.get(ClassName) - IsUnion = TypeInfo.IsUnion if TypeInfo else False - IsCenum = TypeInfo.IsEnum if TypeInfo else False - IsRenum = getattr(TypeInfo, 'IsRenum', False) if TypeInfo else False - - # REnum 处理 - if IsRenum: - if AttrName == 'tag': - ObjVal = self.HandleExprLlvm(Node.value) - if ObjVal: - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - tag_ptr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="tag_ptr") - return Gen._load(tag_ptr, name="tag_val") - NestedStructName = f"{ClassName}_{AttrName}" - if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] - ObjVal = self.HandleExprLlvm(Node.value) - if ObjVal: - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - return Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") - - # CEnum 处理 - if IsCenum: - for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"): - if qname in self.Trans.SymbolTable: - info = self.Trans.SymbolTable[qname] - if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): - return ir.Constant(ir.IntType(32), info.value) - for key, info in self.Trans.SymbolTable.items(): - if key == AttrName: - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == ClassName: - if isinstance(getattr(info, 'value', None), int): - return ir.Constant(ir.IntType(32), info.value) - break - - # CUnion 处理 - if IsUnion: - NestedStructName = f"{ClassName}_{AttrName}" - if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] - ObjVal = self.HandleExprLlvm(Node.value) - if ObjVal: - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - return Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") - - # 普通结构体成员访问 - ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal: - return None - # char* → struct* cast - if self._is_char_pointer(ObjVal): - if ClassName in Gen.structs: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - # 二级指针解引用 - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - - # 检查结构体匹配 - struct_match = self._check_struct_match(Gen, ObjVal, ClassName) - if not struct_match and ClassName and VarName: - if VarName in Gen.var_struct_class: - CN = Gen.var_struct_class[VarName] - if CN != ClassName and CN in Gen.structs: - ClassName = CN - struct_match = self._check_struct_match(Gen, ObjVal, ClassName) - if not struct_match: - return None - - st, ok = self._try_load_struct_from_stub(Gen, ClassName) - if not ok: - return None - - # bitfield 处理 - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - bitfields = Gen.class_member_bitfields.get(ClassName, {}) - if AttrName in bitfield_offsets and bitfields.get(AttrName, 0) > 0: - return self._load_bitfield_member(ObjVal, ClassName, AttrName) - if AttrName in bitfields and bitfields[AttrName] > 0: - if ClassName not in Gen.class_member_bitoffsets: - Gen.class_member_bitoffsets[ClassName] = {} - if AttrName not in Gen.class_member_bitoffsets[ClassName]: - bo = 0 - for bf_name, bf_width in bitfields.items(): - if bf_name == AttrName: - break - bo += bf_width - Gen.class_member_bitoffsets[ClassName][AttrName] = bo - return self._load_bitfield_member(ObjVal, ClassName, AttrName) - - offset = Gen._get_member_offset(AttrName, ClassName) - # 检查 offset 是否超出实际结构体 - if isinstance(ObjVal.type, ir.PointerType): - actual_pointee = ObjVal.type.pointee - if isinstance(actual_pointee, ir.IdentifiedStructType): - actual_elems = actual_pointee.elements - if actual_elems is not None and offset is not None and offset >= len(actual_elems): - self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) - actual_elems = actual_pointee.elements - if actual_elems is not None and offset >= len(actual_elems): - return None - return self._gep_and_load_member(Gen, ObjVal, offset, AttrName, ClassName, st) - - def _handle_attr_nested(self, Node): - """处理 a.b.c 嵌套属性访问""" - Gen = self.Trans.LlvmGen - if isinstance(Node.value.value, ast.Name): - ParentVarName = Node.value.value.id - ParentAttrName = Node.value.attr - enum_result = self._try_resolve_cross_module_enum(ParentVarName, ParentAttrName, Node.attr) - if enum_result is not None: - return enum_result - # 尝试跨模块子模块全局变量解析: a.b.c 其中 a.b 是已知子模块, c 是该模块的全局变量 - imported_modules = getattr(self.Trans, '_imported_modules', None) - if imported_modules: - full_module_path = f"{ParentVarName}.{ParentAttrName}" - if full_module_path in imported_modules: - result = self._lookup_module_global(Gen, full_module_path, Node.attr) - if result is not None: - return result - cdefine_result = self._try_resolve_nested_cdefine(Node) - if cdefine_result is not None: - return cdefine_result - ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): - return None - pointee = ObjVal.type.pointee - - # char* → struct* cast + 成员访问 - if isinstance(pointee, ir.IntType) and pointee.width == 8: - AttrClassName = self._get_attr_class(Node.value, Gen) - if AttrClassName and AttrClassName in Gen.structs: - st, ok = self._try_load_struct_from_stub(Gen, AttrClassName) - if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: - return None - CastedObj = Gen.builder.bitcast(ObjVal, ir.PointerType(st), name=f"cast_{AttrClassName}") - offset = Gen._get_member_offset(Node.attr, AttrClassName) - if offset is None: - return None - if offset < len(st.elements) and isinstance(st.elements[offset], ir.VoidType): - return None - return self._gep_and_load_member(Gen, CastedObj, offset, Node.attr, AttrClassName, st) - - # 已知结构体类型 → 直接成员访问 - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - for CN, ST in Gen.structs.items(): - if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): - st, ok = self._try_load_struct_from_stub(Gen, CN) - if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: - break - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) - if Node.attr in bitfield_offsets: - return self._load_bitfield_member(ObjVal, CN, Node.attr) - offset = Gen._get_member_offset(Node.attr, CN) - if offset is None: - break - return self._gep_and_load_member(Gen, ObjVal, offset, Node.attr, CN, st) - return None - - def _handle_attr_call_result(self, Node): - """处理 func().attr 属性访问""" - Gen = self.Trans.LlvmGen - # Check if this is c.Deref(...) — we need the pointer, not the loaded value - ObjVal = None - is_cderef = (isinstance(Node.value, ast.Call) and - isinstance(Node.value.func, ast.Attribute) and - isinstance(Node.value.func.value, ast.Name) and - Node.value.func.value.id == 'c' and - Node.value.func.attr == 'Deref' and - Node.value.args) - if is_cderef: - deref_arg = Node.value.args[0] - inner_val = self.HandleExprLlvm(deref_arg) - if inner_val and isinstance(inner_val.type, ir.PointerType): - if isinstance(inner_val.type.pointee, ir.PointerType): - ObjVal = Gen._load(inner_val, name="deref_load_ptr") - else: - ObjVal = inner_val - if ObjVal is None: - ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): - return None - pointee = ObjVal.type.pointee - if isinstance(pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") - pointee = ObjVal.type.pointee - found = Gen.find_struct_by_pointee(pointee) - if not found: - return None - CN, ST = found - st, ok = self._try_load_struct_from_stub(Gen, CN) - if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: - return None - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) - if Node.attr in bitfield_offsets: - return self._load_bitfield_member(ObjVal, CN, Node.attr) - offset = Gen._get_member_offset(Node.attr, CN) - if offset is None: - return None - return self._gep_and_load_member(Gen, ObjVal, offset, Node.attr, CN, st) - - def _handle_attr_subscript_result(self, Node): - """处理 arr[i].attr 属性访问""" - Gen = self.Trans.LlvmGen - ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): - return None - pointee = ObjVal.type.pointee - if not isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - return None - found = Gen.find_struct_by_pointee(pointee) - if not found: - return None - CN, ST = found - st, ok = self._try_load_struct_from_stub(Gen, CN) - if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: - return None - offset = Gen._get_member_offset(Node.attr, CN) - if offset is None: - return None - return self._gep_and_load_member(Gen, ObjVal, offset, Node.attr, CN, st) - - def _handle_attr_fallback(self, Node): - """兜底:对任意值尝试指针解引用后查找结构体成员""" - Gen = self.Trans.LlvmGen - ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): - return None - pointee = ObjVal.type.pointee - if isinstance(pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr_fallback") - pointee = ObjVal.type.pointee - if not isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - return None - found = Gen.find_struct_by_pointee(pointee) - if not found: - return None - CN, ST = found - st, ok = self._try_load_struct_from_stub(Gen, CN) - if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: - return None - offset = Gen._get_member_offset(Node.attr, CN) - if offset is None: - return None - return self._gep_and_load_member(Gen, ObjVal, offset, Node.attr, CN, st) - - # ========== 主入口 ========== - - def _HandleAttributeLlvm(self, Node): - Gen = self.Trans.LlvmGen - - if isinstance(Node.value, ast.Name): - VarName = Node.value.id - # 处理 t/c import 的别名重定向 - t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) - if VarName != 'self' and VarName in t_c_imported: - src_module, src_name = t_c_imported[VarName] - virtual_attr = 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._HandleAttributeLlvm(ast.Attribute( - value=virtual_attr, attr=Node.attr, ctx=ast.Load() - )) - if VarName == 'self': - return self._handle_attr_self(Node, VarName) - return self._handle_attr_name(Node, VarName) - - elif isinstance(Node.value, ast.Attribute): - return self._handle_attr_nested(Node) - - elif isinstance(Node.value, ast.Call): - return self._handle_attr_call_result(Node) - - elif isinstance(Node.value, ast.Subscript): - return self._handle_attr_subscript_result(Node) - - # 兜底 - return self._handle_attr_fallback(Node) - - # ========== HandleSubscript 及其辅助 ========== - - def _HandleSubscriptLlvm(self, Node): - Gen = self.Trans.LlvmGen - ClassName = self.Trans.ExprHandler._get_var_class(Node.value, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__getitem__'): - obj_val = self.HandleExprLlvm(Node.value) - idx_val = self.HandleExprLlvm(Node.slice) - if obj_val and idx_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - if isinstance(idx_val.type, ir.IntType) and idx_val.type.width < 64: - idx_val = Gen.builder.zext(idx_val, ir.IntType(64), name="zext_idx") - result = Gen.builder.call(Gen._get_function(f'{ClassName}.__getitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__getitem__") - return result - ValueVal = self.HandleExprLlvm(Node.value) - if not ValueVal: - return None - IndexVal = self.HandleExprLlvm(Node.slice) - if not IndexVal: - return None - if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: - loaded_byte = Gen._load(IndexVal, name="load_char_idx") - IndexVal = Gen.builder.zext(loaded_byte, ir.IntType(32), name="char_to_int_idx") - if isinstance(ValueVal.type, ir.IntType): - var_ptr = self._get_int_ptr(Node.value) - if var_ptr: - i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") - ptr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") - return Gen._load(ptr, name="int_subscript_val") - return None - if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") - if isinstance(ValueVal.type.pointee.pointee, ir.IntType) and ValueVal.type.pointee.pointee.width == 8: - return Gen._load(ElemPtr, name="subscript_val") - return Gen._load(ElemPtr, name="subscript_val") - if isinstance(ValueVal.type, ir.PointerType): - pointee = ValueVal.type.pointee - if isinstance(pointee, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") - elem_type = pointee.element - if isinstance(elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - else: - if isinstance(pointee, ir.IntType) and pointee.width == 8: - elem_class = self._infer_element_struct_class(Node.value, Gen) - if elem_class and elem_class in Gen.structs: - CastedPtr = Gen.builder.bitcast(ValueVal, ir.PointerType(Gen.structs[elem_class]), name=f"cast_{elem_class}_arr") - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_arr_index") - ElemPtr = Gen.builder.gep(CastedPtr, [IndexVal], name="subscript") - if isinstance(pointee, ir.IntType): - return Gen._load(ElemPtr, name="subscript_val") - return ElemPtr - arr_type = self._infer_array_member_type(Node.value, Gen) - if arr_type and isinstance(arr_type, ir.ArrayType): - arr_ptr = Gen.builder.bitcast(ValueVal, ir.PointerType(arr_type), name=f"cast_arr_subscript") - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(arr_ptr, [zero, IndexVal], name="subscript") - arr_elem_type = arr_type.element - if isinstance(arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - elif isinstance(ValueVal.type, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(Node.value, ast.Name): - VarName = Node.value.id - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") - var_arr_elem_type = VarPtr.type.pointee.element - if isinstance(var_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - if isinstance(Node.value, ast.Attribute): - AttrPtr = self._get_attr_ptr(Node.value) - if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") - attr_arr_elem_type = AttrPtr.type.pointee.element - if isinstance(attr_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - if isinstance(Node.value, ast.Subscript): - InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) - if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): - inner_pointee = InnerPtr.type.pointee - if isinstance(inner_pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") - inner_elem_type = inner_pointee.element - if isinstance(inner_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - arr_alloc = Gen._alloca_entry(ValueVal.type, name="arr_subscript_tmp") - Gen._store(ValueVal, arr_alloc) - ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") - alloc_arr_elem_type = ValueVal.type.element - if isinstance(alloc_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): - return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - return None - - def HandleSubscriptPtrLlvm(self, Node): - Gen = self.Trans.LlvmGen - ValueVal = self.HandleExprLlvm(Node.value) - if not ValueVal: - return None - IndexVal = self.HandleExprLlvm(Node.slice) - if not IndexVal: - return None - if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: - loaded_byte = Gen._load(IndexVal, name="load_char_idx_ptr") - IndexVal = Gen.builder.zext(loaded_byte, ir.IntType(32), name="char_to_int_idx_ptr") - if isinstance(ValueVal.type, ir.PointerType): - pointee = ValueVal.type.pointee - if isinstance(pointee, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript_ptr") - return ElemPtr - elif isinstance(pointee, ir.PointerType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index_ptr") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript_ptr") - return ElemPtr - else: - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript_ptr") - return ElemPtr - elif isinstance(ValueVal.type, ir.IntType): - var_ptr = self._get_int_ptr(Node.value) - if var_ptr: - i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") - ElemPtr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") - return ElemPtr - elif isinstance(ValueVal.type, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(Node.value, ast.Name): - VarName = Node.value.id - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript_ptr") - return ElemPtr - if isinstance(Node.value, ast.Subscript): - InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) - if InnerPtr: - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript_ptr") - return ElemPtr - if isinstance(Node.value, ast.Attribute): - AttrPtr = self._get_attr_ptr(Node.value) - if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript_ptr") - return ElemPtr - arr_alloc = Gen._alloca_entry(ValueVal.type, name="arr_subscript_tmp") - Gen._store(ValueVal, arr_alloc) - ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript_ptr") - return ElemPtr - return None - - # ========== _get_attr_ptr / _get_int_ptr / _get_attr_class ========== - - def _get_attr_ptr(self, Node): - Gen = self.Trans.LlvmGen - if not isinstance(Node, ast.Attribute): - return None - if isinstance(Node.value, ast.Name): - VarName = Node.value.id - if VarName == 'self': - ClassName = self.Trans._CurrentCpythonObjectClass - if ClassName: - offset = Gen._get_member_offset(Node.attr, ClassName) - SelfVar = Gen._get_var_ptr('self') - if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - if isinstance(SelfPtr.type, ir.PointerType): - MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) - return MemberPtr - ClassName = Gen.var_struct_class.get(VarName) - if not ClassName and getattr(Gen, 'global_struct_class', None): - ClassName = Gen.global_struct_class.get(VarName) - if not ClassName: - imported_modules = getattr(self.Trans, '_imported_modules', None) - import_aliases = getattr(self.Trans, '_import_aliases', {}) - resolved_mod = import_aliases.get(VarName, VarName) - if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): - AttrName = Node.attr - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - candidates = [VarName, resolved_mod] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - if mod_name not in candidates: - candidates.append(mod_name) - for cand in candidates: - sha1 = module_sha1_map.get(cand) - if sha1: - prefixed = f"{sha1}.{AttrName}" - if prefixed in Gen.module.globals: - return Gen.module.globals[prefixed] - if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] - if isinstance(gv, ir.GlobalVariable): - return gv - if ClassName and ClassName in Gen.structs: - VarPtr = Gen.variables.get(VarName) - if VarPtr: - ObjVal = VarPtr - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"load_{VarName}") - if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: - ST = Gen.structs[ClassName] - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) - ST = Gen.structs.get(ClassName, ST) - if ST.elements is not None and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{ClassName}") - offset = Gen._get_member_offset(Node.attr, ClassName) - if offset is not None and ST.elements is not None: - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) - return MemberPtr - elif isinstance(Node.value, ast.Attribute): - InnerPtr = self._get_attr_ptr(Node.value) - if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): - pointee = InnerPtr.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) - ST = Gen.structs.get(CN, ST) - if ST.elements is not None and isinstance(InnerPtr.type, ir.PointerType) and isinstance(InnerPtr.type.pointee, ir.IdentifiedStructType) and InnerPtr.type.pointee.elements is None: - InnerPtr = Gen.builder.bitcast(InnerPtr, ir.PointerType(ST), name=f"cast_{CN}") - offset = Gen._get_member_offset(Node.attr, CN) - if offset is not None and ST.elements is not None: - MemberPtr = Gen.builder.gep(InnerPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) - return MemberPtr - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - AttrClassName = self._get_attr_class(Node.value, Gen) - if AttrClassName and AttrClassName in Gen.structs: - CastedObj = Gen.builder.bitcast(InnerPtr, ir.PointerType(Gen.structs[AttrClassName]), name=f"cast_{AttrClassName}") - offset = Gen._get_member_offset(Node.attr, AttrClassName) - if offset is not None: - MemberPtr = Gen.builder.gep(CastedObj, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) - return MemberPtr - elif isinstance(Node.value, ast.Subscript): - SubPtr = self.HandleSubscriptPtrLlvm(Node.value) - if SubPtr and isinstance(SubPtr.type, ir.PointerType): - pointee = SubPtr.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - offset = Gen._get_member_offset(Node.attr, CN) - if offset is not None: - MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) - return MemberPtr - return None - - def _HandleSliceLlvm(self, base_val, slice_node, base_ast): - Gen = self.Trans.LlvmGen - lower_val = None - upper_val = None - step_val = None - if isinstance(slice_node, ast.Slice): - if slice_node.lower: - lower_val = self.HandleExprLlvm(slice_node.lower) - if slice_node.upper: - upper_val = self.HandleExprLlvm(slice_node.upper) - if slice_node.step: - step_val = self.HandleExprLlvm(slice_node.step) - if isinstance(slice_node, ast.Index): - return self.HandleExprLlvm(slice_node.value) - return None - - def _infer_element_struct_class(self, node, Gen): - if isinstance(node, ast.Attribute): - attr_name = node.attr - if isinstance(node.value, ast.Name) and node.value.id == 'self': - current_class = self.Trans._CurrentCpythonObjectClass - if current_class: - if current_class in Gen.class_member_element_class: - elem_class = Gen.class_member_element_class[current_class].get(attr_name) - if elem_class and elem_class in Gen.structs: - return elem_class - if current_class in Gen.class_members: - for member_name, member_type in Gen.class_members[current_class]: - if member_name == attr_name: - if isinstance(member_type, ir.IdentifiedStructType): - found = Gen.find_struct_by_pointee(member_type) - if found: - return found[0] - break - class_name = Gen.var_struct_class.get(attr_name) - if class_name: - return class_name - elif isinstance(node, ast.Name): - var_name = node.id - class_name = Gen.var_struct_class.get(var_name) - if class_name: - return class_name - return None - - def _get_int_ptr(self, target): - Gen = self.Trans.LlvmGen - if isinstance(target, ast.Name): - VarName = target.id - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee - if isinstance(pointee, ir.ArrayType): - return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") - return VarPtr - elif isinstance(target, ast.Attribute): - if isinstance(target.value, ast.Name): - obj_name = target.value.id - if obj_name in Gen.variables and Gen.variables[obj_name] is not None: - obj_ptr = Gen.variables[obj_name] - if isinstance(obj_ptr.type, ir.PointerType): - pointee = obj_ptr.type.pointee - if isinstance(pointee, ir.PointerType): - obj_ptr = Gen._load(obj_ptr, name=f"load_{obj_name}") - pointee = obj_ptr.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - StructName = None - if isinstance(pointee, ir.IdentifiedStructType): - StructName = pointee.name - if not StructName: - found = Gen.find_struct_by_pointee(pointee) - if found: - StructName = found[0] - if StructName and StructName in Gen.structs: - offset = Gen._get_member_offset(target.attr, StructName) - if offset is not None: - return Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") - obj_val = self.HandleExprLlvm(target.value) - if obj_val and isinstance(obj_val.type, ir.PointerType): - if isinstance(obj_val.type.pointee, ir.PointerType): - obj_val = Gen._load(obj_val, name="load_attr_ptr") - pointee = obj_val.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - StructName = None - if isinstance(pointee, ir.IdentifiedStructType): - StructName = pointee.name - if not StructName: - found = Gen.find_struct_by_pointee(pointee) - if found: - StructName = found[0] - if StructName and StructName in Gen.structs: - offset = Gen._get_member_offset(target.attr, StructName) - if offset is not None: - return Gen.builder.gep(obj_val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") - return None - - def _resolve_struct_class_for_attr(self, Node, Gen): - if isinstance(Node, ast.Name): - VarName = Node.id - if VarName in Gen.var_struct_class: - return Gen.var_struct_class[VarName] - elif isinstance(Node, ast.Attribute): - ClassName = self._resolve_struct_class_for_attr(Node.value, Gen) - if ClassName and ClassName in Gen.class_members: - for member_name, _ in Gen.class_members[ClassName]: - if member_name == Node.attr: - return ClassName - return None - - def _infer_array_member_type(self, Node, Gen): - if isinstance(Node, ast.Attribute): - parent_class = self._get_attr_class(Node, Gen) - if parent_class and parent_class in Gen.class_members: - for m_name, m_type in Gen.class_members[parent_class]: - if m_name == Node.attr and isinstance(m_type, ir.ArrayType): - return m_type - if parent_class and parent_class in Gen.structs: - st = Gen.structs[parent_class] - if isinstance(st, ir.IdentifiedStructType) and st.elements is not None: - offset = Gen._get_member_offset(Node.attr, parent_class) - if offset is not None and offset < len(st.elements): - elem = st.elements[offset] - if isinstance(elem, ir.ArrayType): - return elem - return None - - def _build_attr_path(self, node): - parts = [] - current = node - while isinstance(current, ast.Attribute): - parts.append(current.attr) - current = current.value - if isinstance(current, ast.Name): - parts.append(current.id) - parts.reverse() - return parts - - def _try_resolve_nested_cdefine(self, Node): - Gen = self.Trans.LlvmGen - imported_modules = getattr(self.Trans, '_imported_modules', None) - if not imported_modules: - return None - import_aliases = getattr(self.Trans, '_import_aliases', {}) - parts = self._build_attr_path(Node) - if len(parts) < 2: - return None - attr_name = parts[-1] - module_parts = parts[:-1] - possible_keys = [attr_name] - full_path = '.'.join(parts) - possible_keys.append(full_path) - if module_parts: - module_path = '.'.join(module_parts) - resolved_first = import_aliases.get(module_parts[0], module_parts[0]) - if resolved_first != module_parts[0]: - resolved_parts = [resolved_first] + module_parts[1:] - resolved_path = '.'.join(resolved_parts) - possible_keys.append(f"{resolved_path}.{attr_name}") - for mod_name in imported_modules: - if mod_name.endswith('.' + module_path) or mod_name == module_path: - key = f"{mod_name}.{attr_name}" - if key not in possible_keys: - possible_keys.append(key) - if module_parts and (mod_name.endswith('.' + module_parts[-1]) or mod_name == module_parts[-1]): - key = f"{mod_name}.{attr_name}" - if key not in possible_keys: - possible_keys.append(key) - for lookup_key in possible_keys: - SymInfo = self.Trans.SymbolTable.get(lookup_key) - if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: - val = SymInfo.DefineValue - if isinstance(val, int): - if val > 0x7FFFFFFF or val < -0x80000000: - return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) - return ir.Constant(ir.IntType(32), val) - elif isinstance(val, float): - return ir.Constant(ir.FloatType(), val) - return None - - def _try_resolve_cross_module_enum(self, module_alias, enum_class_name, member_name): - Gen = self.Trans.LlvmGen - imported_modules = getattr(self.Trans, '_imported_modules', None) - if not imported_modules: - return None - import_aliases = getattr(self.Trans, '_import_aliases', {}) - resolved_module = import_aliases.get(module_alias, module_alias) - if resolved_module not in imported_modules and module_alias not in imported_modules: - return None - enum_keys = [enum_class_name, f"{resolved_module}.{enum_class_name}"] - for enum_key in enum_keys: - if enum_key in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[enum_key] - if getattr(SymInfo, 'IsEnum', None): - for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"): - if qname in self.Trans.SymbolTable: - info = self.Trans.SymbolTable[qname] - if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): - return ir.Constant(ir.IntType(32), info.value) - for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_key and key == member_name: - if isinstance(getattr(info, 'value', None), int): - return ir.Constant(ir.IntType(32), info.value) - for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and key == member_name: - if isinstance(getattr(info, 'value', None), int): - for enum_key in enum_keys: - if getattr(info, 'EnumName', None) == enum_key: - return ir.Constant(ir.IntType(32), info.value) - return None - - def _get_attr_class(self, Node, Gen): - if isinstance(Node, ast.Attribute): - # 注: 不再硬编码 ZLIB_VERSION / C_OK,它们应从符号表查找 - if isinstance(Node.value, ast.Name) and Node.value.id == 'self': - ClassName = self.Trans._CurrentCpythonObjectClass - if ClassName and ClassName in Gen.class_member_element_class: - return Gen.class_member_element_class[ClassName].get(Node.attr) - if isinstance(Node.value, ast.Name): - VarName = Node.value.id - if VarName in Gen.var_struct_class: - ParentClass = Gen.var_struct_class[VarName] - if ParentClass in Gen.class_member_element_class: - return Gen.class_member_element_class[ParentClass].get(Node.attr) - if isinstance(Node.value, ast.Attribute): - ParentClass = self._get_attr_class(Node.value, Gen) - if ParentClass and ParentClass in Gen.class_member_element_class: - return Gen.class_member_element_class[ParentClass].get(Node.attr) - return None - - def _get_llvm_member_offset(self, field_name, ClassName, Gen): - return Gen._get_member_offset(field_name, ClassName) - - def _load_bitfield_member(self, struct_ptr, ClassName, field_name): - Gen = self.Trans.LlvmGen - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - bitfield_widths = Gen.class_member_bitfields.get(ClassName, {}) - if field_name not in bitfield_offsets: - return None - bit_offset = bitfield_offsets[field_name] - bit_width = bitfield_widths.get(field_name, 0) - if bit_width == 0: - return None - struct_type = Gen.structs.get(ClassName) - if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: - return None - storage_type = struct_type.elements[0] - member_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") - storage_val = Gen._load(member_ptr, name=f"{field_name}_storage") - shift_amount = bit_offset - if shift_amount > 0: - shifted = Gen.builder.lshr(storage_val, ir.Constant(storage_type, shift_amount), name=f"{field_name}_shift") - else: - shifted = storage_val - mask = (1 << bit_width) - 1 - masked = Gen.builder.and_(shifted, ir.Constant(storage_type, mask), name=f"{field_name}_mask") - is_signed = Gen.class_member_signeds.get(ClassName, {}).get(field_name, False) - if is_signed and bit_width > 0: - sign_bit = 1 << (bit_width - 1) - sign_masked = Gen.builder.and_(shifted, ir.Constant(storage_type, sign_bit), name=f"{field_name}_sign") - sign_extend = Gen.builder.icmp_signed('!=', sign_masked, ir.Constant(storage_type, 0), name=f"{field_name}_sign_check") - extended = Gen.builder.select(sign_extend, - Gen.builder.sext(masked, ir.IntType(32), name=f"{field_name}_sext"), - Gen.builder.zext(masked, ir.IntType(32), name=f"{field_name}_zext"), - name=f"{field_name}_extend") - return extended +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, FuncMeta +import ast +import llvmlite.ir as ir + + +class ExprAttrHandle(BaseHandle): + + # ========== 辅助方法 ========== + + def _apply_bswap_on_Load(self, val, ClassName, AttrName): + Gen = self.Trans.LlvmGen + byte_order = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") + if byte_order == 'big' and isinstance(val.type, ir.IntType): + if val.type.width in (16, 32, 64): + val = Gen.builder.bswap(val, name=f"bswap_Load_{AttrName}") + return val + + def _gep_and_Load_member(self, Gen, ObjVal, offset, AttrName, ClassName, ST=None): + """从结构体指针通过 GEP 取成员,处理 array/struct pointer/class_members 特殊情况""" + if offset is None: + return None + if isinstance(ObjVal.type, ir.PointerType): + pointee = ObjVal.type.pointee + if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is not None and offset >= len(pointee.elements): + return None + MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.ArrayType): + return MemberPtr + if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.IdentifiedStructType): + return MemberPtr + # 检查 pointer-to-pointer 且实际元素是 ArrayType + if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.PointerType): + actual_elem_type = None + if ST is not None and isinstance(ST, ir.IdentifiedStructType) and ST.elements is not None and offset < len(ST.elements): + actual_elem_type = ST.elements[offset] + if isinstance(actual_elem_type, ir.ArrayType): + return Gen.builder.bitcast(MemberPtr, ir.PointerType(actual_elem_type), name=f"cast_arr_{AttrName}") + # 检查 class_members 中的 ArrayType + if ClassName in Gen.class_members: + for member_name, member_type in Gen.class_members[ClassName]: + if member_name == AttrName and isinstance(member_type, ir.ArrayType): + return Gen.builder.bitcast(MemberPtr, ir.PointerType(member_type), name=f"cast_arr_{AttrName}") + val = Gen._load(MemberPtr, name=AttrName) + return self._apply_bswap_on_Load(val, ClassName, AttrName) + + def _try_Load_struct_from_stub(self, Gen, ClassName): + """尝试从 stub 加载结构体定义,返回 (struct_type, ok)""" + if ClassName not in Gen.structs: + return None, False + st = Gen.structs[ClassName] + if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) + st = Gen.structs.get(ClassName, st) + if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): + return st, False + return st, True + + def _make_define_constant(self, Gen, val): + """将 CDefine 值转为 LLVM 常量""" + if isinstance(val, int): + if abs(val) > 2147483647: + return ir.Constant(ir.IntType(64), val) + return ir.Constant(ir.IntType(32), val) + elif isinstance(val, float): + return ir.Constant(ir.DoubleType(), val) + elif isinstance(val, str): + str_value = val + '\x00' + str_bytes = str_value.encode('utf-8') + str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) + 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 + return Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return None + + def _lookup_cdefine(self, Gen, VarName, AttrName): + """在符号表和模块中查找 CDefine 常量值""" + imported_modules = getattr(self.Trans, '_ImportedModules', None) + if not imported_modules: + return None + PossibleKeys = [f"{VarName}.{AttrName}", AttrName] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + key = f"{mod_name}.{AttrName}" + if key not in PossibleKeys: + PossibleKeys.append(key) + for lookup_key in PossibleKeys: + SymInfo = self.Trans.SymbolTable.get(lookup_key) + if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: + return self._make_define_constant(Gen, SymInfo.DefineValue) + # 也检查 _define_constants + define_constants = getattr(Gen, '_define_constants', {}) + for key in (f"{VarName}.{AttrName}", AttrName): + if key in define_constants: + return self._make_define_constant(Gen, define_constants[key]) + return None + + def _lookup_module_global(self, Gen, VarName, AttrName): + """在模块全局变量中查找 import 的属性""" + imported_modules = getattr(self.Trans, '_ImportedModules', None) + import_aliases = getattr(self.Trans, '_ImportAliases', {}) + if not imported_modules: + return None + resolved_mod = import_aliases.get(VarName, VarName) + if VarName not in imported_modules and resolved_mod not in imported_modules: + return None + PossibleKeys = [f"{VarName}.{AttrName}", AttrName] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + key = f"{mod_name}.{AttrName}" + if key not in PossibleKeys: + PossibleKeys.append(key) + for key in PossibleKeys: + if key in Gen.module.globals: + GVar = Gen.module.globals[key] + 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=AttrName) + # SHA1 前缀查找 + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + sha1_candidates = [VarName, resolved_mod] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + if mod_name not in sha1_candidates: + sha1_candidates.append(mod_name) + for cand in sha1_candidates: + sha1 = ModuleSha1Map.get(cand) + if sha1: + prefixed = f"{sha1}.{AttrName}" + if prefixed in Gen.module.globals: + GVar2 = Gen.module.globals[prefixed] + if isinstance(GVar2, ir.Function): + return GVar2 + if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar2 + return Gen._load(GVar2, name=AttrName) + if AttrName in Gen.module.globals: + gv = Gen.module.globals[AttrName] + if AttrName in Gen.variables and Gen.variables[AttrName] is None: + str_gv_name = AttrName + '_str' + if str_gv_name in Gen.module.globals: + str_gv = Gen.module.globals[str_gv_name] + return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") + return Gen.builder.load(gv, name=AttrName) + return None + + def _resolve_var_classname(self, Gen, VarName): + """根据变量名解析其结构体类名""" + ClassName = Gen.var_struct_class.get(VarName) + if not ClassName and getattr(Gen, 'global_struct_class', None): + ClassName = Gen.global_struct_class.get(VarName) + if ClassName: + Gen.var_struct_class[VarName] = ClassName + if not ClassName and VarName in Gen.module.globals: + GVar = Gen.module.globals[VarName] + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + found = Gen.find_struct_by_pointee(GVar.type.pointee) + if found: + ClassName = found[0] + Gen.var_struct_class[VarName] = ClassName + if getattr(Gen, 'global_struct_class', None): + Gen.global_struct_class[VarName] = ClassName + if not ClassName and VarName in Gen.variables: + VarPtr = Gen.variables[VarName] + if VarPtr is not None and isinstance(VarPtr.type, ir.PointerType): + pointee = VarPtr.type.pointee + if isinstance(pointee, ir.PointerType): + pointee = pointee.pointee + found = Gen.find_struct_by_pointee(pointee) + if found: + ClassName = found[0] + return ClassName + + def _check_struct_match(self, Gen, ObjVal, ClassName): + """检查 ObjVal 是否指向 ClassName 对应的结构体""" + if ClassName not in Gen.structs: + return False + if isinstance(ObjVal.type, ir.PointerType): + ST = Gen.structs[ClassName] + if ObjVal.type.pointee == ST: + return True + if isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and ObjVal.type.pointee.name == ST.name: + return True + return False + + # ========== _HandleAttributeLlvm 子方法 ========== + + def _handle_attr_self(self, Node, VarName): + """处理 self.xxx 属性访问""" + Gen = self.Trans.LlvmGen + ClassName = self.Trans._CurrentCpythonObjectClass + if not ClassName: + return None + # 检查 property getter + PropKey = f'{ClassName}.{Node.attr}' + PropInfo = self.Trans.SymbolTable.get(PropKey) + if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: + SelfVar = Gen._get_var_ptr('self') + if SelfVar: + SelfPtr = Gen._load(SelfVar, name="self") + GetterFunc = Gen._get_function(PropKey) + if GetterFunc and SelfPtr: + return Gen.builder.call(GetterFunc, [SelfPtr], name=f"prop_{PropKey}") + offset = Gen._get_member_offset(Node.attr, ClassName) + SelfVar = Gen._get_var_ptr('self') + if not SelfVar: + return None + SelfPtr = Gen._load(SelfVar, name="self") + if not isinstance(SelfPtr.type, ir.PointerType): + return None + pointee = SelfPtr.type.pointee + if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: + for CN2, ST2 in Gen.structs.items(): + if isinstance(ST2, ir.IdentifiedStructType) and ST2.name == pointee.name and ST2.elements is not None: + pointee = ST2 + break + if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is not None and offset is not None and offset < len(pointee.elements): + if isinstance(pointee.elements[offset], ir.VoidType): + return None + return self._gep_and_Load_member(Gen, SelfPtr, offset, Node.attr, ClassName, pointee) + DynamicVarName = f"self.{Node.attr}" + if DynamicVarName in Gen.variables: + return Gen._load(Gen.variables[DynamicVarName], name=Node.attr) + return None + + def _handle_attr_enum(self, Node, VarName): + """处理枚举成员访问 (VarName 是枚举类型名)""" + SymInfo = self.Trans.SymbolTable.get(VarName) + if not SymInfo or not getattr(SymInfo, 'IsEnum', None): + return None + if Node.attr in self.Trans.SymbolTable: + MemberInfo = self.Trans.SymbolTable[Node.attr] + if getattr(MemberInfo, 'IsEnumMember', None) and getattr(MemberInfo, 'EnumName', None) == VarName: + if isinstance(getattr(MemberInfo, 'value', None), int): + return ir.Constant(ir.IntType(32), MemberInfo.value) + for key, info in self.Trans.SymbolTable.items(): + if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == VarName and key == Node.attr: + if isinstance(getattr(info, 'value', None), int): + return ir.Constant(ir.IntType(32), info.value) + return None + + def _handle_attr_name(self, Node, VarName): + """处理 x.attr 形式 (x 是普通 Name)""" + Gen = self.Trans.LlvmGen + AttrName = Node.attr + + # 先尝试枚举成员 + result = self._handle_attr_enum(Node, VarName) + if result is not None: + return result + + # 尝试 CDefine 常量 + result = self._lookup_cdefine(Gen, VarName, AttrName) + if result is not None: + return result + + # 尝试 import 模块全局变量 + result = self._lookup_module_global(Gen, VarName, AttrName) + if result is not None: + return result + + # 尝试 attr 直接作为全局变量 + if AttrName in Gen.module.globals: + gv = Gen.module.globals[AttrName] + if AttrName in Gen.variables and Gen.variables[AttrName] is None: + str_gv_name = AttrName + '_str' + if str_gv_name in Gen.module.globals: + str_gv = Gen.module.globals[str_gv_name] + return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") + return Gen.builder.load(gv, name=AttrName) + + # 解析结构体类名并访问成员 + ClassName = self._resolve_var_classname(Gen, VarName) + if not ClassName: + return None + + # 检查 property getter + PropKey = f'{ClassName}.{AttrName}' + PropInfo = self.Trans.SymbolTable.get(PropKey) + if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: + ObjVal = self.HandleExprLlvm(Node.value) + GetterFunc = Gen._get_function(PropKey) + if GetterFunc and ObjVal: + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + return Gen.builder.call(GetterFunc, [ObjVal], name=f"prop_{PropKey}") + + # 获取类型信息 + TypeInfo = self.Trans.SymbolTable.get(ClassName) + IsUnion = TypeInfo.IsUnion if TypeInfo else False + IsCenum = TypeInfo.IsEnum if TypeInfo else False + IsRenum = getattr(TypeInfo, 'IsRenum', False) if TypeInfo else False + + # REnum 处理 + if IsRenum: + if AttrName == 'tag': + ObjVal = self.HandleExprLlvm(Node.value) + if ObjVal: + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + tag_ptr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="tag_ptr") + return Gen._load(tag_ptr, name="tag_val") + NestedStructName = f"{ClassName}_{AttrName}" + if NestedStructName in Gen.structs: + NestedStructType = Gen.structs[NestedStructName] + ObjVal = self.HandleExprLlvm(Node.value) + if ObjVal: + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + return Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") + + # CEnum 处理 + if IsCenum: + for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"): + if qname in self.Trans.SymbolTable: + info = self.Trans.SymbolTable[qname] + if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): + return ir.Constant(ir.IntType(32), info.value) + for key, info in self.Trans.SymbolTable.items(): + if key == AttrName: + if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == ClassName: + if isinstance(getattr(info, 'value', None), int): + return ir.Constant(ir.IntType(32), info.value) + break + + # CUnion 处理 + if IsUnion: + NestedStructName = f"{ClassName}_{AttrName}" + if NestedStructName in Gen.structs: + NestedStructType = Gen.structs[NestedStructName] + ObjVal = self.HandleExprLlvm(Node.value) + if ObjVal: + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + return Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") + + # 普通结构体成员访问 + ObjVal = self.HandleExprLlvm(Node.value) + if not ObjVal: + return None + # char* → struct* cast + if self._is_char_pointer(ObjVal): + if ClassName in Gen.structs: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + # 二级指针解引用 + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + + # 检查结构体匹配 + struct_match = self._check_struct_match(Gen, ObjVal, ClassName) + if not struct_match and ClassName and VarName: + if VarName in Gen.var_struct_class: + CN = Gen.var_struct_class[VarName] + if CN != ClassName and CN in Gen.structs: + ClassName = CN + struct_match = self._check_struct_match(Gen, ObjVal, ClassName) + if not struct_match: + return None + + st, ok = self._try_Load_struct_from_stub(Gen, ClassName) + if not ok: + return None + + # bitfield 处理 + bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) + bitfields = Gen.class_member_bitfields.get(ClassName, {}) + if AttrName in bitfield_offsets and bitfields.get(AttrName, 0) > 0: + return self._load_bitfield_member(ObjVal, ClassName, AttrName) + if AttrName in bitfields and bitfields[AttrName] > 0: + if ClassName not in Gen.class_member_bitoffsets: + Gen.class_member_bitoffsets[ClassName] = {} + if AttrName not in Gen.class_member_bitoffsets[ClassName]: + bo = 0 + for bf_name, bf_width in bitfields.items(): + if bf_name == AttrName: + break + bo += bf_width + Gen.class_member_bitoffsets[ClassName][AttrName] = bo + return self._load_bitfield_member(ObjVal, ClassName, AttrName) + + offset = Gen._get_member_offset(AttrName, ClassName) + # 检查 offset 是否超出实际结构体 + if isinstance(ObjVal.type, ir.PointerType): + actual_pointee = ObjVal.type.pointee + if isinstance(actual_pointee, ir.IdentifiedStructType): + actual_elems = actual_pointee.elements + if actual_elems is not None and offset is not None and offset >= len(actual_elems): + self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) + actual_elems = actual_pointee.elements + if actual_elems is not None and offset >= len(actual_elems): + return None + return self._gep_and_Load_member(Gen, ObjVal, offset, AttrName, ClassName, st) + + def _handle_attr_nested(self, Node): + """处理 a.b.c 嵌套属性访问""" + Gen = self.Trans.LlvmGen + if isinstance(Node.value.value, ast.Name): + ParentVarName = Node.value.value.id + ParentAttrName = Node.value.attr + enum_result = self._try_resolve_cross_module_enum(ParentVarName, ParentAttrName, Node.attr) + if enum_result is not None: + return enum_result + # 尝试跨模块子模块全局变量解析: a.b.c 其中 a.b 是已知子模块, c 是该模块的全局变量 + imported_modules = getattr(self.Trans, '_ImportedModules', None) + if imported_modules: + full_ModulePath = f"{ParentVarName}.{ParentAttrName}" + if full_ModulePath in imported_modules: + result = self._lookup_module_global(Gen, full_ModulePath, Node.attr) + if result is not None: + return result + cdefine_result = self._try_resolve_nested_cdefine(Node) + if cdefine_result is not None: + return cdefine_result + ObjVal = self.HandleExprLlvm(Node.value) + if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): + return None + pointee = ObjVal.type.pointee + + # char* → struct* cast + 成员访问 + if isinstance(pointee, ir.IntType) and pointee.width == 8: + AttrClassName = self._get_attr_class(Node.value, Gen) + if AttrClassName and AttrClassName in Gen.structs: + st, ok = self._try_Load_struct_from_stub(Gen, AttrClassName) + if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + return None + CastedObj = Gen.builder.bitcast(ObjVal, ir.PointerType(st), name=f"cast_{AttrClassName}") + offset = Gen._get_member_offset(Node.attr, AttrClassName) + if offset is None: + return None + if offset < len(st.elements) and isinstance(st.elements[offset], ir.VoidType): + return None + return self._gep_and_Load_member(Gen, CastedObj, offset, Node.attr, AttrClassName, st) + + # 已知结构体类型 → 直接成员访问 + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + for CN, ST in Gen.structs.items(): + if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): + st, ok = self._try_Load_struct_from_stub(Gen, CN) + if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + break + bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) + if Node.attr in bitfield_offsets: + return self._load_bitfield_member(ObjVal, CN, Node.attr) + offset = Gen._get_member_offset(Node.attr, CN) + if offset is None: + break + return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) + return None + + def _handle_attr_call_result(self, Node): + """处理 func().attr 属性访问""" + Gen = self.Trans.LlvmGen + # Check if this is c.Deref(...) — we need the pointer, not the Loaded value + ObjVal = None + is_cderef = (isinstance(Node.value, ast.Call) and + isinstance(Node.value.func, ast.Attribute) and + isinstance(Node.value.func.value, ast.Name) and + Node.value.func.value.id == 'c' and + Node.value.func.attr == 'Deref' and + Node.value.args) + if is_cderef: + deref_arg = Node.value.args[0] + inner_val = self.HandleExprLlvm(deref_arg) + if inner_val and isinstance(inner_val.type, ir.PointerType): + if isinstance(inner_val.type.pointee, ir.PointerType): + ObjVal = Gen._load(inner_val, name="deref_load_ptr") + else: + ObjVal = inner_val + if ObjVal is None: + ObjVal = self.HandleExprLlvm(Node.value) + if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): + return None + pointee = ObjVal.type.pointee + if isinstance(pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") + pointee = ObjVal.type.pointee + found = Gen.find_struct_by_pointee(pointee) + if not found: + return None + CN, ST = found + st, ok = self._try_Load_struct_from_stub(Gen, CN) + if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + return None + bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) + if Node.attr in bitfield_offsets: + return self._load_bitfield_member(ObjVal, CN, Node.attr) + offset = Gen._get_member_offset(Node.attr, CN) + if offset is None: + return None + return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) + + def _handle_attr_subscript_result(self, Node): + """处理 arr[i].attr 属性访问""" + Gen = self.Trans.LlvmGen + ObjVal = self.HandleExprLlvm(Node.value) + if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): + return None + pointee = ObjVal.type.pointee + if not isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + return None + found = Gen.find_struct_by_pointee(pointee) + if not found: + return None + CN, ST = found + st, ok = self._try_Load_struct_from_stub(Gen, CN) + if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + return None + offset = Gen._get_member_offset(Node.attr, CN) + if offset is None: + return None + return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) + + def _handle_attr_fallback(self, Node): + """兜底:对任意值尝试指针解引用后查找结构体成员""" + Gen = self.Trans.LlvmGen + ObjVal = self.HandleExprLlvm(Node.value) + if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): + return None + pointee = ObjVal.type.pointee + if isinstance(pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr_fallback") + pointee = ObjVal.type.pointee + if not isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + return None + found = Gen.find_struct_by_pointee(pointee) + if not found: + return None + CN, ST = found + st, ok = self._try_Load_struct_from_stub(Gen, CN) + if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: + return None + offset = Gen._get_member_offset(Node.attr, CN) + if offset is None: + return None + return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) + + # ========== 主入口 ========== + + def _HandleAttributeLlvm(self, Node): + Gen = self.Trans.LlvmGen + + if isinstance(Node.value, ast.Name): + VarName = Node.value.id + # 处理 t/c import 的别名重定向 + t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) + if VarName != 'self' and VarName in t_c_imported: + src_module, src_name = t_c_imported[VarName] + virtual_attr = 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._HandleAttributeLlvm(ast.Attribute( + value=virtual_attr, attr=Node.attr, ctx=ast.Load() + )) + if VarName == 'self': + return self._handle_attr_self(Node, VarName) + return self._handle_attr_name(Node, VarName) + + elif isinstance(Node.value, ast.Attribute): + return self._handle_attr_nested(Node) + + elif isinstance(Node.value, ast.Call): + return self._handle_attr_call_result(Node) + + elif isinstance(Node.value, ast.Subscript): + return self._handle_attr_subscript_result(Node) + + # 兜底 + return self._handle_attr_fallback(Node) + + # ========== HandleSubscript 及其辅助 ========== + + def _HandleSubscriptLlvm(self, Node): + Gen = self.Trans.LlvmGen + ClassName = self.Trans.ExprHandler._get_var_class(Node.value, Gen) + if ClassName and Gen._has_function(f'{ClassName}.__getitem__'): + obj_val = self.HandleExprLlvm(Node.value) + idx_val = self.HandleExprLlvm(Node.slice) + if obj_val and idx_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + if isinstance(idx_val.type, ir.IntType) and idx_val.type.width < 64: + idx_val = Gen.builder.zext(idx_val, ir.IntType(64), name="zext_idx") + result = Gen.builder.call(Gen._get_function(f'{ClassName}.__getitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__getitem__") + return result + ValueVal = self.HandleExprLlvm(Node.value) + if not ValueVal: + return None + IndexVal = self.HandleExprLlvm(Node.slice) + if not IndexVal: + return None + if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: + Loaded_byte = Gen._load(IndexVal, name="Load_char_idx") + IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx") + if isinstance(ValueVal.type, ir.IntType): + var_ptr = self._get_int_ptr(Node.value) + if var_ptr: + i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") + ptr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") + return Gen._load(ptr, name="int_subscript_val") + return None + if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index") + ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") + if isinstance(ValueVal.type.pointee.pointee, ir.IntType) and ValueVal.type.pointee.pointee.width == 8: + return Gen._load(ElemPtr, name="subscript_val") + return Gen._load(ElemPtr, name="subscript_val") + if isinstance(ValueVal.type, ir.PointerType): + pointee = ValueVal.type.pointee + if isinstance(pointee, ir.ArrayType): + zero = ir.Constant(ir.IntType(32), 0) + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") + elem_type = pointee.element + if isinstance(elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + else: + if isinstance(pointee, ir.IntType) and pointee.width == 8: + elem_class = self._infer_element_struct_class(Node.value, Gen) + if elem_class and elem_class in Gen.structs: + CastedPtr = Gen.builder.bitcast(ValueVal, ir.PointerType(Gen.structs[elem_class]), name=f"cast_{elem_class}_arr") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_arr_index") + ElemPtr = Gen.builder.gep(CastedPtr, [IndexVal], name="subscript") + if isinstance(pointee, ir.IntType): + return Gen._load(ElemPtr, name="subscript_val") + return ElemPtr + arr_type = self._infer_array_member_type(Node.value, Gen) + if arr_type and isinstance(arr_type, ir.ArrayType): + arr_ptr = Gen.builder.bitcast(ValueVal, ir.PointerType(arr_type), name=f"cast_arr_subscript") + zero = ir.Constant(ir.IntType(32), 0) + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(arr_ptr, [zero, IndexVal], name="subscript") + arr_elem_type = arr_type.element + if isinstance(arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + elif isinstance(ValueVal.type, ir.ArrayType): + zero = ir.Constant(ir.IntType(32), 0) + if isinstance(Node.value, ast.Name): + VarName = Node.value.id + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") + var_arr_elem_type = VarPtr.type.pointee.element + if isinstance(var_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + if isinstance(Node.value, ast.Attribute): + AttrPtr = self._get_attr_ptr(Node.value) + if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") + attr_arr_elem_type = AttrPtr.type.pointee.element + if isinstance(attr_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + if isinstance(Node.value, ast.Subscript): + InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) + if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): + inner_pointee = InnerPtr.type.pointee + if isinstance(inner_pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") + inner_elem_type = inner_pointee.element + if isinstance(inner_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") + Gen._store(ValueVal, arr_alloc) + ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") + alloc_arr_elem_type = ValueVal.type.element + if isinstance(alloc_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): + return ElemPtr + return Gen._load(ElemPtr, name="subscript_val") + return None + + def HandleSubscriptPtrLlvm(self, Node): + Gen = self.Trans.LlvmGen + ValueVal = self.HandleExprLlvm(Node.value) + if not ValueVal: + return None + IndexVal = self.HandleExprLlvm(Node.slice) + if not IndexVal: + return None + if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: + Loaded_byte = Gen._load(IndexVal, name="Load_char_idx_ptr") + IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_ptr") + if isinstance(ValueVal.type, ir.PointerType): + pointee = ValueVal.type.pointee + if isinstance(pointee, ir.ArrayType): + zero = ir.Constant(ir.IntType(32), 0) + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript_ptr") + return ElemPtr + elif isinstance(pointee, ir.PointerType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index_ptr") + ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript_ptr") + return ElemPtr + else: + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index") + ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript_ptr") + return ElemPtr + elif isinstance(ValueVal.type, ir.IntType): + var_ptr = self._get_int_ptr(Node.value) + if var_ptr: + i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") + ElemPtr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") + return ElemPtr + elif isinstance(ValueVal.type, ir.ArrayType): + zero = ir.Constant(ir.IntType(32), 0) + if isinstance(Node.value, ast.Name): + VarName = Node.value.id + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript_ptr") + return ElemPtr + if isinstance(Node.value, ast.Subscript): + InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) + if InnerPtr: + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript_ptr") + return ElemPtr + if isinstance(Node.value, ast.Attribute): + AttrPtr = self._get_attr_ptr(Node.value) + if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript_ptr") + return ElemPtr + arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") + Gen._store(ValueVal, arr_alloc) + ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript_ptr") + return ElemPtr + return None + + # ========== _get_attr_ptr / _get_int_ptr / _get_attr_class ========== + + def _get_attr_ptr(self, Node): + Gen = self.Trans.LlvmGen + if not isinstance(Node, ast.Attribute): + return None + if isinstance(Node.value, ast.Name): + VarName = Node.value.id + if VarName == 'self': + ClassName = self.Trans._CurrentCpythonObjectClass + if ClassName: + offset = Gen._get_member_offset(Node.attr, ClassName) + SelfVar = Gen._get_var_ptr('self') + if SelfVar: + SelfPtr = Gen._load(SelfVar, name="self") + if isinstance(SelfPtr.type, ir.PointerType): + MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + return MemberPtr + ClassName = Gen.var_struct_class.get(VarName) + if not ClassName and getattr(Gen, 'global_struct_class', None): + ClassName = Gen.global_struct_class.get(VarName) + if not ClassName: + imported_modules = getattr(self.Trans, '_ImportedModules', None) + import_aliases = getattr(self.Trans, '_ImportAliases', {}) + resolved_mod = import_aliases.get(VarName, VarName) + if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): + AttrName = Node.attr + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + candidates = [VarName, resolved_mod] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + if mod_name not in candidates: + candidates.append(mod_name) + for cand in candidates: + sha1 = ModuleSha1Map.get(cand) + if sha1: + prefixed = f"{sha1}.{AttrName}" + if prefixed in Gen.module.globals: + return Gen.module.globals[prefixed] + if AttrName in Gen.module.globals: + gv = Gen.module.globals[AttrName] + if isinstance(gv, ir.GlobalVariable): + return gv + if ClassName and ClassName in Gen.structs: + VarPtr = Gen.variables.get(VarName) + if VarPtr: + ObjVal = VarPtr + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") + if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: + ST = Gen.structs[ClassName] + if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) + ST = Gen.structs.get(ClassName, ST) + if ST.elements is not None and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{ClassName}") + offset = Gen._get_member_offset(Node.attr, ClassName) + if offset is not None and ST.elements is not None: + MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + return MemberPtr + elif isinstance(Node.value, ast.Attribute): + InnerPtr = self._get_attr_ptr(Node.value) + if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): + pointee = InnerPtr.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + found = Gen.find_struct_by_pointee(pointee) + if found: + CN, ST = found + if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) + ST = Gen.structs.get(CN, ST) + if ST.elements is not None and isinstance(InnerPtr.type, ir.PointerType) and isinstance(InnerPtr.type.pointee, ir.IdentifiedStructType) and InnerPtr.type.pointee.elements is None: + InnerPtr = Gen.builder.bitcast(InnerPtr, ir.PointerType(ST), name=f"cast_{CN}") + offset = Gen._get_member_offset(Node.attr, CN) + if offset is not None and ST.elements is not None: + MemberPtr = Gen.builder.gep(InnerPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + return MemberPtr + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + AttrClassName = self._get_attr_class(Node.value, Gen) + if AttrClassName and AttrClassName in Gen.structs: + CastedObj = Gen.builder.bitcast(InnerPtr, ir.PointerType(Gen.structs[AttrClassName]), name=f"cast_{AttrClassName}") + offset = Gen._get_member_offset(Node.attr, AttrClassName) + if offset is not None: + MemberPtr = Gen.builder.gep(CastedObj, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + return MemberPtr + elif isinstance(Node.value, ast.Subscript): + SubPtr = self.HandleSubscriptPtrLlvm(Node.value) + if SubPtr and isinstance(SubPtr.type, ir.PointerType): + pointee = SubPtr.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + found = Gen.find_struct_by_pointee(pointee) + if found: + CN, ST = found + offset = Gen._get_member_offset(Node.attr, CN) + if offset is not None: + MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + return MemberPtr + return None + + def _HandleSliceLlvm(self, base_val, slice_node, base_ast): + Gen = self.Trans.LlvmGen + lower_val = None + upper_val = None + step_val = None + if isinstance(slice_node, ast.Slice): + if slice_node.lower: + lower_val = self.HandleExprLlvm(slice_node.lower) + if slice_node.upper: + upper_val = self.HandleExprLlvm(slice_node.upper) + if slice_node.step: + step_val = self.HandleExprLlvm(slice_node.step) + if isinstance(slice_node, ast.Index): + return self.HandleExprLlvm(slice_node.value) + return None + + def _infer_element_struct_class(self, node, Gen): + if isinstance(node, ast.Attribute): + attr_name = node.attr + if isinstance(node.value, ast.Name) and node.value.id == 'self': + current_class = self.Trans._CurrentCpythonObjectClass + if current_class: + if current_class in Gen.class_member_element_class: + elem_class = Gen.class_member_element_class[current_class].get(attr_name) + if elem_class and elem_class in Gen.structs: + return elem_class + if current_class in Gen.class_members: + for member_name, member_type in Gen.class_members[current_class]: + if member_name == attr_name: + if isinstance(member_type, ir.IdentifiedStructType): + found = Gen.find_struct_by_pointee(member_type) + if found: + return found[0] + break + class_name = Gen.var_struct_class.get(attr_name) + if class_name: + return class_name + elif isinstance(node, ast.Name): + var_name = node.id + class_name = Gen.var_struct_class.get(var_name) + if class_name: + return class_name + return None + + def _get_int_ptr(self, target): + Gen = self.Trans.LlvmGen + if isinstance(target, ast.Name): + VarName = target.id + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType): + pointee = VarPtr.type.pointee + if isinstance(pointee, ir.ArrayType): + return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") + return VarPtr + elif isinstance(target, ast.Attribute): + if isinstance(target.value, ast.Name): + obj_name = target.value.id + if obj_name in Gen.variables and Gen.variables[obj_name] is not None: + obj_ptr = Gen.variables[obj_name] + if isinstance(obj_ptr.type, ir.PointerType): + pointee = obj_ptr.type.pointee + if isinstance(pointee, ir.PointerType): + obj_ptr = Gen._load(obj_ptr, name=f"Load_{obj_name}") + pointee = obj_ptr.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + StructName = None + if isinstance(pointee, ir.IdentifiedStructType): + StructName = pointee.name + if not StructName: + found = Gen.find_struct_by_pointee(pointee) + if found: + StructName = found[0] + if StructName and StructName in Gen.structs: + offset = Gen._get_member_offset(target.attr, StructName) + if offset is not None: + return Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") + obj_val = self.HandleExprLlvm(target.value) + if obj_val and isinstance(obj_val.type, ir.PointerType): + if isinstance(obj_val.type.pointee, ir.PointerType): + obj_val = Gen._load(obj_val, name="Load_attr_ptr") + pointee = obj_val.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + StructName = None + if isinstance(pointee, ir.IdentifiedStructType): + StructName = pointee.name + if not StructName: + found = Gen.find_struct_by_pointee(pointee) + if found: + StructName = found[0] + if StructName and StructName in Gen.structs: + offset = Gen._get_member_offset(target.attr, StructName) + if offset is not None: + return Gen.builder.gep(obj_val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") + return None + + def _resolve_struct_class_for_attr(self, Node, Gen): + if isinstance(Node, ast.Name): + VarName = Node.id + if VarName in Gen.var_struct_class: + return Gen.var_struct_class[VarName] + elif isinstance(Node, ast.Attribute): + ClassName = self._resolve_struct_class_for_attr(Node.value, Gen) + if ClassName and ClassName in Gen.class_members: + for member_name, _ in Gen.class_members[ClassName]: + if member_name == Node.attr: + return ClassName + return None + + def _infer_array_member_type(self, Node, Gen): + if isinstance(Node, ast.Attribute): + parent_class = self._get_attr_class(Node, Gen) + if parent_class and parent_class in Gen.class_members: + for m_name, m_type in Gen.class_members[parent_class]: + if m_name == Node.attr and isinstance(m_type, ir.ArrayType): + return m_type + if parent_class and parent_class in Gen.structs: + st = Gen.structs[parent_class] + if isinstance(st, ir.IdentifiedStructType) and st.elements is not None: + offset = Gen._get_member_offset(Node.attr, parent_class) + if offset is not None and offset < len(st.elements): + elem = st.elements[offset] + if isinstance(elem, ir.ArrayType): + return elem + return None + + def _build_attr_path(self, node): + parts = [] + current = node + while isinstance(current, ast.Attribute): + parts.append(current.attr) + current = current.value + if isinstance(current, ast.Name): + parts.append(current.id) + parts.reverse() + return parts + + def _try_resolve_nested_cdefine(self, Node): + Gen = self.Trans.LlvmGen + imported_modules = getattr(self.Trans, '_ImportedModules', None) + if not imported_modules: + return None + import_aliases = getattr(self.Trans, '_ImportAliases', {}) + parts = self._build_attr_path(Node) + if len(parts) < 2: + return None + attr_name = parts[-1] + module_parts = parts[:-1] + possible_keys = [attr_name] + full_path = '.'.join(parts) + possible_keys.append(full_path) + if module_parts: + ModulePath = '.'.join(module_parts) + resolved_first = import_aliases.get(module_parts[0], module_parts[0]) + if resolved_first != module_parts[0]: + resolved_parts = [resolved_first] + module_parts[1:] + resolved_path = '.'.join(resolved_parts) + possible_keys.append(f"{resolved_path}.{attr_name}") + for mod_name in imported_modules: + if mod_name.endswith('.' + ModulePath) or mod_name == ModulePath: + key = f"{mod_name}.{attr_name}" + if key not in possible_keys: + possible_keys.append(key) + if module_parts and (mod_name.endswith('.' + module_parts[-1]) or mod_name == module_parts[-1]): + key = f"{mod_name}.{attr_name}" + if key not in possible_keys: + possible_keys.append(key) + for lookup_key in possible_keys: + SymInfo = self.Trans.SymbolTable.get(lookup_key) + if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: + val = SymInfo.DefineValue + if isinstance(val, int): + if val > 0x7FFFFFFF or val < -0x80000000: + return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) + return ir.Constant(ir.IntType(32), val) + elif isinstance(val, float): + return ir.Constant(ir.FloatType(), val) + return None + + def _try_resolve_cross_module_enum(self, module_alias, enum_class_name, member_name): + Gen = self.Trans.LlvmGen + imported_modules = getattr(self.Trans, '_ImportedModules', None) + if not imported_modules: + return None + import_aliases = getattr(self.Trans, '_ImportAliases', {}) + resolved_module = import_aliases.get(module_alias, module_alias) + if resolved_module not in imported_modules and module_alias not in imported_modules: + return None + enum_keys = [enum_class_name, f"{resolved_module}.{enum_class_name}"] + for enum_key in enum_keys: + if enum_key in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[enum_key] + if getattr(SymInfo, 'IsEnum', None): + for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"): + if qname in self.Trans.SymbolTable: + info = self.Trans.SymbolTable[qname] + if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): + return ir.Constant(ir.IntType(32), info.value) + for key, info in self.Trans.SymbolTable.items(): + if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_key and key == member_name: + if isinstance(getattr(info, 'value', None), int): + return ir.Constant(ir.IntType(32), info.value) + for key, info in self.Trans.SymbolTable.items(): + if getattr(info, 'IsEnumMember', None) and key == member_name: + if isinstance(getattr(info, 'value', None), int): + for enum_key in enum_keys: + if getattr(info, 'EnumName', None) == enum_key: + return ir.Constant(ir.IntType(32), info.value) + return None + + def _get_attr_class(self, Node, Gen): + if isinstance(Node, ast.Attribute): + # 注: 不再硬编码 ZLIB_VERSION / C_OK,它们应从符号表查找 + if isinstance(Node.value, ast.Name) and Node.value.id == 'self': + ClassName = self.Trans._CurrentCpythonObjectClass + if ClassName and ClassName in Gen.class_member_element_class: + return Gen.class_member_element_class[ClassName].get(Node.attr) + if isinstance(Node.value, ast.Name): + VarName = Node.value.id + if VarName in Gen.var_struct_class: + ParentClass = Gen.var_struct_class[VarName] + if ParentClass in Gen.class_member_element_class: + return Gen.class_member_element_class[ParentClass].get(Node.attr) + if isinstance(Node.value, ast.Attribute): + ParentClass = self._get_attr_class(Node.value, Gen) + if ParentClass and ParentClass in Gen.class_member_element_class: + return Gen.class_member_element_class[ParentClass].get(Node.attr) + return None + + def _get_llvm_member_offset(self, field_name, ClassName, Gen): + return Gen._get_member_offset(field_name, ClassName) + + def _Load_bitfield_member(self, struct_ptr, ClassName, field_name): + Gen = self.Trans.LlvmGen + bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) + bitfield_widths = Gen.class_member_bitfields.get(ClassName, {}) + if field_name not in bitfield_offsets: + return None + bit_offset = bitfield_offsets[field_name] + bit_width = bitfield_widths.get(field_name, 0) + if bit_width == 0: + return None + struct_type = Gen.structs.get(ClassName) + if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: + return None + storage_type = struct_type.elements[0] + member_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") + storage_val = Gen._load(member_ptr, name=f"{field_name}_storage") + shift_amount = bit_offset + if shift_amount > 0: + shifted = Gen.builder.lshr(storage_val, ir.Constant(storage_type, shift_amount), name=f"{field_name}_shift") + else: + shifted = storage_val + mask = (1 << bit_width) - 1 + masked = Gen.builder.and_(shifted, ir.Constant(storage_type, mask), name=f"{field_name}_mask") + is_signed = Gen.class_member_signeds.get(ClassName, {}).get(field_name, False) + if is_signed and bit_width > 0: + sign_bit = 1 << (bit_width - 1) + sign_masked = Gen.builder.and_(shifted, ir.Constant(storage_type, sign_bit), name=f"{field_name}_sign") + sign_extend = Gen.builder.icmp_signed('!=', sign_masked, ir.Constant(storage_type, 0), name=f"{field_name}_sign_check") + extended = Gen.builder.select(sign_extend, + Gen.builder.sext(masked, ir.IntType(32), name=f"{field_name}_sext"), + Gen.builder.zext(masked, ir.IntType(32), name=f"{field_name}_zext"), + name=f"{field_name}_extend") + return extended return Gen.builder.zext(masked, ir.IntType(32), name=f"{field_name}_zext") \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 0bb130e..6b7c02c 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -56,9 +56,9 @@ class ExprBuiltinHandle(BaseHandle): if isinstance(Val.type, ir.IntType): if Val.type.width == 1: return Val - return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result") + return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") elif isinstance(Val.type, ir.PointerType): - return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result") + return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") return Val return ir.Constant(ir.IntType(1), 0) elif FuncName == 'int': @@ -254,7 +254,7 @@ class ExprBuiltinHandle(BaseHandle): val = Gen.builder.zext(val, ir.IntType(32), name="zext_bool_print") elif val.type.width == 8: if self._is_char_type(arg): - char_var = Gen._alloca_entry(ir.IntType(8), name="print_char_buf") + char_var = Gen._allocaEntry(ir.IntType(8), name="print_char_buf") Gen.builder.store(val, char_var) fmt_parts.append('%c') fmt_args.append(char_var) @@ -316,7 +316,7 @@ class ExprBuiltinHandle(BaseHandle): if ClassName in Gen.structs: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [obj_val], name=f"call_{ClassName}.__str__") - Gen._register_temp_ptr(str_val) + Gen._RegisterTempPtr(str_val) Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) else: val = self.HandleExprLlvm(arg) @@ -325,7 +325,7 @@ class ExprBuiltinHandle(BaseHandle): pointee = val.type.pointee if not (isinstance(pointee, ir.IntType) and pointee.width == 8): try: - val = Gen._load(val, name="print_load") + val = Gen._load(val, name="print_Load") except Exception as _e: if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") @@ -394,7 +394,7 @@ class ExprBuiltinHandle(BaseHandle): if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: - result = self.Trans.ExprUtils._try_operator_overload(CN, '__len__', val, Gen) + result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__len__', val, Gen) if result is not None: return result break @@ -442,8 +442,12 @@ class ExprBuiltinHandle(BaseHandle): size_bits = getattr(ctype_inst, 'Size', 0) or 0 size_bytes = size_bits // 8 return ir.Constant(ir.IntType(64), size_bytes) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") resolved = CTypeRegistry.ResolveName(type_name) if resolved: ctype_cls, ptr_level = resolved @@ -454,8 +458,12 @@ class ExprBuiltinHandle(BaseHandle): if ptr_level > 0: size_bytes = 8 return ir.Constant(ir.IntType(64), size_bytes) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") return ir.Constant(ir.IntType(64), 0) struct_type = Gen.structs[type_name] @@ -479,7 +487,7 @@ class ExprBuiltinHandle(BaseHandle): if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: - result = self.Trans.ExprUtils._try_operator_overload(CN, '__abs__', val, Gen) + result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__abs__', val, Gen) if result is not None: return result break @@ -525,12 +533,12 @@ class ExprBuiltinHandle(BaseHandle): if TypeInfo.IsEnum: enum_type_name = arg_name elif isinstance(arg, ast.Attribute): - last_part = None + LastPart = None enum_class_name = None if isinstance(arg.value, ast.Name): - last_part = arg.attr - if last_part in self.Trans.SymbolTable: - AttrInfo = self.Trans.SymbolTable[last_part] + LastPart = arg.attr + if LastPart in self.Trans.SymbolTable: + AttrInfo = self.Trans.SymbolTable[LastPart] if getattr(AttrInfo, 'IsEnumMember', None) and getattr(AttrInfo, 'EnumName', None): enum_type_name = AttrInfo.EnumName elif isinstance(arg.value, ast.Attribute): @@ -539,9 +547,9 @@ class ExprBuiltinHandle(BaseHandle): parts = attr_path.split('.') if len(parts) >= 2: enum_class_name = parts[-2] - last_part = parts[-1] - qualified_name_dot = f"{enum_class_name}.{last_part}" - qualified_name_under = f"{enum_class_name}_{last_part}" + LastPart = parts[-1] + qualified_name_dot = f"{enum_class_name}.{LastPart}" + qualified_name_under = f"{enum_class_name}_{LastPart}" enum_member_found = None for qname in (qualified_name_dot, qualified_name_under): if qname in self.Trans.SymbolTable: @@ -551,7 +559,7 @@ class ExprBuiltinHandle(BaseHandle): break if not enum_member_found: for key in self.Trans.SymbolTable: - if key == last_part: + if key == LastPart: info = self.Trans.SymbolTable[key] if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_class_name: enum_member_found = info diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 5082730..e1f08ef 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -48,9 +48,9 @@ class ExprCallHandle(BaseHandle): elif arg.name == '__eh_code_out__' and eh_code_ptr is None: eh_code_ptr = arg if eh_msg_ptr is None: - eh_msg_ptr = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") + eh_msg_ptr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") if eh_code_ptr is None: - eh_code_ptr = Gen._alloca_entry(ir.IntType(32), name="eh_code_out_null") + eh_code_ptr = Gen._allocaEntry(ir.IntType(32), name="eh_code_out_null") Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_msg_ptr) Gen._store(ir.Constant(ir.IntType(32), 0), eh_code_ptr) CallArgs.append(eh_msg_ptr) @@ -83,7 +83,7 @@ class ExprCallHandle(BaseHandle): elif arg.name == '__eh_code_out__' and eh_code_ptr is None: eh_code_ptr = arg if eh_msg_ptr is not None: - eh_msg_val = Gen._load(eh_msg_ptr, name=f"load_eh_msg_{func_name}") + eh_msg_val = Gen._load(eh_msg_ptr, name=f"Load_eh_msg_{func_name}") null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) is_error = Gen.builder.icmp_signed('!=', eh_msg_val, null_ptr, name=f"check_eh_msg_{func_name}") OkBB = Gen.func.append_basic_block(name=f"ok_after_{func_name}") @@ -114,7 +114,7 @@ class ExprCallHandle(BaseHandle): ExceptBB, _, exception_code, _ = Gen.eh_except_block_stack[-1] if ExceptBB is not None: if has_eh_code_out and eh_code_ptr is not None: - eh_code_val = Gen._load(eh_code_ptr, name=f"load_eh_code_{func_name}") + eh_code_val = Gen._load(eh_code_ptr, name=f"Load_eh_code_{func_name}") Gen._store(eh_code_val, exception_code) else: Gen._store(ir.Constant(ir.IntType(32), 1), exception_code) @@ -199,8 +199,8 @@ class ExprCallHandle(BaseHandle): def _HandleCallLlvm(self, Node): Gen = self.Trans.LlvmGen - func_attr = None - module_path = None + FuncAttr = None + ModulePath = None if isinstance(Node.func, ast.Name): FuncName = Node.func.id if hasattr(self.Trans.FunctionHandler, '_generic_templates') and FuncName in self.Trans.FunctionHandler._generic_templates: @@ -231,9 +231,9 @@ class ExprCallHandle(BaseHandle): if isinstance(Val.type, ir.IntType): if Val.type.width == 1: return Val - return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result") + return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") elif isinstance(Val.type, ir.PointerType): - return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result") + return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") return Val return ir.Constant(ir.IntType(1), 0) elif FuncName == 'int': @@ -355,7 +355,7 @@ class ExprCallHandle(BaseHandle): return self._HandleCallLlvm(virtual_node) # 检查是否是闭包变量(lambda 赋值给变量后调用) if FuncName in Gen.variables and Gen.variables[FuncName] is not None: - closure_ptr = Gen._load(Gen.variables[FuncName], name=f"load_closure_{FuncName}") + closure_ptr = Gen._load(Gen.variables[FuncName], name=f"Load_closure_{FuncName}") if isinstance(closure_ptr.type, ir.PointerType) and isinstance(closure_ptr.type.pointee, ir.LiteralStructType): st = closure_ptr.type.pointee if len(st.elements) == 2 and isinstance(st.elements[1], ir.PointerType) and isinstance(st.elements[1].pointee, ir.FunctionType): @@ -428,30 +428,30 @@ class ExprCallHandle(BaseHandle): type_name = Node.func.value.attr SizeofNode = ast.Name(id=type_name, ctx=ast.Load()) return self._HandleSizeofLlvm(SizeofNode) - module_path = self._get_module_path(Node.func.value) - if module_path: - aliases = getattr(self.Trans, '_import_aliases', {}) - first_part = module_path.split('.')[0] + ModulePath = self._get_ModulePath(Node.func.value) + if ModulePath: + aliases = getattr(self.Trans, '_ImportAliases', {}) + first_part = ModulePath.split('.')[0] if first_part in aliases: - module_path = aliases[first_part] + module_path[len(first_part):] - is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.module_sha1_map + ModulePath = aliases[first_part] + ModulePath[len(first_part):] + is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[Node.func.value.id], 'IsStruct', False))) if is_instance_var and not is_class_name: return self._HandleMethodCallLlvm(Node) - func_attr = Node.func.attr - if func_attr in Gen.structs: - result = self._HandleClassNewLlvm(Node, func_attr) + FuncAttr = Node.func.attr + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result - if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and func_attr in self.Trans.ClassHandler._generic_class_templates: - return self._HandleGenericClassNewLlvm(Node, func_attr) - if func_attr in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[func_attr] + if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and FuncAttr in self.Trans.ClassHandler._generic_class_templates: + return self._HandleGenericClassNewLlvm(Node, FuncAttr) + if FuncAttr in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[FuncAttr] if SymInfo.IsStruct: - if func_attr not in Gen.structs: - self._ensure_struct_declared(func_attr) - if func_attr in Gen.structs: - result = self._HandleClassNewLlvm(Node, func_attr) + if FuncAttr not in Gen.structs: + self._ensure_struct_declared(FuncAttr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None): @@ -459,58 +459,58 @@ class ExprCallHandle(BaseHandle): if EnumName in self.Trans.SymbolTable: EnumInfo = self.Trans.SymbolTable[EnumName] if getattr(EnumInfo, 'IsRenum', False): - result = self._HandleREnumConstructLlvm(Node, EnumName, func_attr, SymInfo.value) + result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value) if result is not None: return result - FullAttrKey = f"{module_path}.{func_attr}" + FullAttrKey = f"{ModulePath}.{FuncAttr}" if FullAttrKey in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[FullAttrKey] if SymInfo.IsStruct: - if func_attr not in Gen.structs: - self._ensure_struct_declared(func_attr) - if func_attr in Gen.structs: - result = self._HandleClassNewLlvm(Node, func_attr) + if FuncAttr not in Gen.structs: + self._ensure_struct_declared(FuncAttr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result if is_class_name: ClassName = Node.func.value.id - result = self._HandleStaticMethodCallLlvm(Node, ClassName, func_attr) + result = self._HandleStaticMethodCallLlvm(Node, ClassName, FuncAttr) if result is not None: return result - FullAttrKey = f"{module_path}.{func_attr}" + FullAttrKey = f"{ModulePath}.{FuncAttr}" if FullAttrKey in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[FullAttrKey] if getattr(SymInfo, 'IsTypedef', False): return ir.Constant(ir.IntType(32), 0) if getattr(SymInfo, 'IsStruct', False): - if func_attr not in Gen.structs: - self._ensure_struct_declared(func_attr) - if func_attr in Gen.structs: - result = self._HandleClassNewLlvm(Node, func_attr) + if FuncAttr not in Gen.structs: + self._ensure_struct_declared(FuncAttr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result - if func_attr in Gen.structs: - result = self._HandleClassNewLlvm(Node, func_attr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result - if module_path == 'c': - if func_attr == 'Asm': + if ModulePath == 'c': + if FuncAttr == 'Asm': return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node) - elif func_attr == 'Addr': + elif FuncAttr == 'Addr': return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node) - elif func_attr == 'Set': + elif FuncAttr == 'Set': return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node) - elif func_attr == 'Load': + elif FuncAttr == 'Load': return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node) - elif func_attr == 'Deref': + elif FuncAttr == 'Deref': return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node) - elif func_attr == 'DerefAs': + elif FuncAttr == 'DerefAs': return self._HandleCDerefAsLlvm(Node) - elif func_attr == 'PtrToInt': + elif FuncAttr == 'PtrToInt': return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node) - elif func_attr in ('CIf', 'CElif'): + elif FuncAttr in ('CIf', 'CElif'): return self.Trans.CSpecialCallHandle._HandleCIfLlvm(Node) - elif func_attr == 'CError': + elif FuncAttr == 'CError': msg = "compile-time error" if Node.args: arg = Node.args[0] @@ -520,52 +520,119 @@ class ExprCallHandle(BaseHandle): msg = arg.s lineno = getattr(Node, 'lineno', 0) raise Exception(f"#error: {msg} (line {lineno})") - elif func_attr in ('AsmInp', 'AsmOut'): + elif FuncAttr in ('AsmInp', 'AsmOut'): return ir.Constant(ir.IntType(32), 0) - elif func_attr == 'LLVMIR': + elif FuncAttr == 'LLVMIR': return self._HandleLLVMIRLlvm(Node) - elif func_attr in ('LInp', 'LOut'): + elif FuncAttr in ('LInp', 'LOut'): return ir.Constant(ir.IntType(32), 0) - if module_path == 't': - method_result_t = self._HandleMethodCallLlvm(Node) - if method_result_t is not None: - return method_result_t - raise Exception(f"Undefined method: 't.{func_attr}'") + if ModulePath == 't': + MethodResult_t = self._HandleMethodCallLlvm(Node) + if MethodResult_t is not None: + return MethodResult_t + raise Exception(f"Undefined method: 't.{FuncAttr}'") if isinstance(Node.func.value, ast.Attribute): inner_attr = Node.func.value.attr if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[inner_attr], 'IsStruct', False)): - static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, func_attr) + static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr) if static_result is not None: return static_result - method_result_attr = self._HandleMethodCallLlvm(Node) - is_zero_attr = isinstance(method_result_attr, ir.Constant) and isinstance(method_result_attr.type, ir.IntType) and method_result_attr.constant == 0 - if method_result_attr is not None and not is_zero_attr: - return method_result_attr - result = self._HandleExternalCallLlvm(Node, func_attr, module_path) + MethodResult_attr = self._HandleMethodCallLlvm(Node) + is_zero_attr = isinstance(MethodResult_attr, ir.Constant) and isinstance(MethodResult_attr.type, ir.IntType) and MethodResult_attr.constant == 0 + if MethodResult_attr is not None and not is_zero_attr: + return MethodResult_attr + result = self._HandleExternalCallLlvm(Node, FuncAttr, ModulePath) if result is not None: return result - method_result = self._HandleMethodCallLlvm(Node) - is_zero_result = isinstance(method_result, ir.Constant) and isinstance(method_result.type, ir.IntType) and method_result.constant == 0 - if is_zero_result and func_attr is not None: - mangled_name = Gen._mangle_func_name(func_attr, module_path if module_path and module_path != 't' else None) + MethodResult = self._HandleMethodCallLlvm(Node) + IsZeroResult = isinstance(MethodResult, ir.Constant) and isinstance(MethodResult.type, ir.IntType) and MethodResult.constant == 0 + if IsZeroResult and FuncAttr is not None: + mangled_name = Gen._mangle_func_name(FuncAttr, ModulePath if ModulePath and ModulePath != 't' else None) if Gen._has_function(mangled_name): CallArgs = [] for arg in Node.args: ArgVal = self.HandleExprLlvm(arg) if ArgVal: CallArgs.append(ArgVal) - return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{func_attr}") - if method_result is None or is_zero_result: - imported = getattr(self.Trans, '_imported_modules', set()) - aliases = getattr(self.Trans, '_import_aliases', {}) - is_known = module_path in imported or module_path in aliases - if module_path and is_known: - raise Exception(f"Undefined symbol: '{module_path}.{func_attr}'") - if module_path and module_path not in {'t', 'c'} and not is_known: - raise Exception(f"Unknown module: '{module_path}' (undefined symbol: '{module_path}.{func_attr}')") - if not module_path and func_attr: - raise Exception(f"Undefined method: '{func_attr}'") - return method_result if method_result is not None else ir.Constant(ir.IntType(32), 0) + return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{FuncAttr}") + if MethodResult is None or IsZeroResult: + imported = getattr(self.Trans, '_ImportedModules', set()) + aliases = getattr(self.Trans, '_ImportAliases', {}) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + IsKnown = (ModulePath in imported or ModulePath in aliases or + ModulePath in ModuleSha1Map) + if not IsKnown and ModulePath and '.' in ModulePath: + LastPart = ModulePath.split('.')[-1] + IsKnown = (LastPart in imported or LastPart in aliases or + LastPart in ModuleSha1Map) + # 最后尝试: 用 FuncAttr 直接查找 Gen.functions(_find_function 会遍历 SHA1 前缀) + if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}: + # 优先检查 FuncAttr 是否为 struct/类构造器 + if FuncAttr not in Gen.structs: + self._ensure_struct_declared(FuncAttr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) + if result is not None: + return result + # 检查 FullAttrKey 是否为 struct(如 hashlib.md5) + if ModulePath: + FullAttrKey = f"{ModulePath}.{FuncAttr}" + if FullAttrKey in self.Trans.SymbolTable: + FullSymInfo = self.Trans.SymbolTable[FullAttrKey] + if getattr(FullSymInfo, 'IsStruct', False) or getattr(FullSymInfo, 'IsCpythonObject', False): + if FuncAttr not in Gen.structs: + self._ensure_struct_declared(FuncAttr) + if FuncAttr in Gen.structs: + result = self._HandleClassNewLlvm(Node, FuncAttr) + if result is not None: + return result + fallback_func = Gen._find_function(FuncAttr) + if fallback_func is not None: + CallArgs = [] + for arg in Node.args: + ArgVal = self.HandleExprLlvm(arg) + if ArgVal: + CallArgs.append(ArgVal) + self._append_eh_msg_out_arg(CallArgs, fallback_func, Gen) + result = Gen.builder.call(fallback_func, CallArgs, name=f"call_{FuncAttr}") + return self._check_eh_return(result, FuncAttr, Gen, called_func=fallback_func) + # 尝试从 stub 按需加载函数声明 + if ModulePath in ModuleSha1Map: + sha1 = ModuleSha1Map[ModulePath] + stub_mangled = f"{sha1}.{FuncAttr}" + try: + stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(stub_mangled, Gen) + except Exception: + stub_func_type = None + if not stub_func_type: + try: + stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(FuncAttr, Gen) + except Exception: + stub_func_type = None + if stub_func_type: + decl_name = stub_mangled if stub_mangled in getattr(self.Trans.ImportHandler, '_stub_func_cache', {}) else FuncAttr + if decl_name not in Gen.functions: + func_decl = ir.Function(Gen.module, stub_func_type, name=decl_name) + Gen.functions[decl_name] = func_decl + if decl_name != FuncAttr and FuncAttr not in Gen.functions: + Gen.functions[FuncAttr] = func_decl + else: + func_decl = Gen.functions[decl_name] + CallArgs = [] + for arg in Node.args: + ArgVal = self.HandleExprLlvm(arg) + if ArgVal: + CallArgs.append(ArgVal) + self._append_eh_msg_out_arg(CallArgs, func_decl, Gen) + result = Gen.builder.call(func_decl, CallArgs, name=f"call_{FuncAttr}") + return self._check_eh_return(result, FuncAttr, Gen, called_func=func_decl) + if ModulePath and IsKnown: + raise Exception(f"Undefined symbol: '{ModulePath}.{FuncAttr}'") + if ModulePath and ModulePath not in {'t', 'c'} and not IsKnown: + raise Exception(f"Unknown module: '{ModulePath}' (undefined symbol: '{ModulePath}.{FuncAttr}')") + if not ModulePath and FuncAttr: + raise Exception(f"Undefined method: '{FuncAttr}'") + return MethodResult if MethodResult is not None else ir.Constant(ir.IntType(32), 0) if isinstance(Node.func, ast.BinOp) and isinstance(Node.func.op, ast.BitOr): return self._HandleTypeUnionCastLlvm(Node) raise Exception(f"Unsupported call expression") @@ -771,7 +838,7 @@ class ExprCallHandle(BaseHandle): ast.copy_location(new_node, Node) return new_node - def _get_module_path(self, node): + def _get_ModulePath(self, node): parts = [] while isinstance(node, ast.Attribute): parts.append(node.attr) @@ -936,9 +1003,9 @@ class ExprCallHandle(BaseHandle): result = method(src_val, dest_type, name="llvmir_result") return self._StoreLLVMIROutputs(Gen, result, output_targets) - load_match = re.match(r'load\s+(\w+),\s*(\w+)\s+%__OP(\d+)__', template) - if load_match: - ptr_val = resolve_op(int(load_match.group(3))) + Load_match = re.match(r'Load\s+(\w+),\s*(\w+)\s+%__OP(\d+)__', template) + if Load_match: + ptr_val = resolve_op(int(Load_match.group(3))) if ptr_val: result = Gen.builder.load(ptr_val, name="llvmir_result") return self._StoreLLVMIROutputs(Gen, result, output_targets) @@ -1095,8 +1162,8 @@ class ExprCallHandle(BaseHandle): expected_type = self._ParseLLVMType(Gen, expected_type_str.rstrip('*')) if not expected_type: return val - is_ptr = expected_type_str.endswith('*') - if is_ptr: + IsPtr = expected_type_str.endswith('*') + if IsPtr: expected_ptr_type = ir.PointerType(expected_type) if isinstance(val.type, ir.PointerType) and val.type != expected_ptr_type: try: @@ -1124,31 +1191,32 @@ class ExprCallHandle(BaseHandle): return Gen.builder.inttoptr(val, expected_type) return val - def _HandleExternalCallLlvm(self, Node, func_name, module_path): + def _HandleExternalCallLlvm(self, Node, func_name, ModulePath): Gen = self.Trans.LlvmGen # 解析 import 别名: 如 window -> vpsdk.window - if module_path and module_path not in ('c', 't'): - import_aliases = getattr(self.Trans, '_import_aliases', {}) - if module_path in import_aliases: - module_path = import_aliases[module_path] + if ModulePath and ModulePath not in ('c', 't'): + import_aliases = getattr(self.Trans, '_ImportAliases', {}) + if ModulePath in import_aliases: + ModulePath = import_aliases[ModulePath] - is_user_module = (module_path and module_path not in ('c', 't') and - (module_path in Gen.module_sha1_map or - module_path in getattr(self.Trans, '_imported_modules', set()) or - module_path in getattr(self.Trans, '_import_aliases', {}))) - if module_path and module_path not in ('c', 't') and not is_user_module: - is_user_module = (module_path in Gen.module_sha1_map or - module_path.split('.')[-1] in Gen.module_sha1_map) - if is_user_module and module_path not in Gen.module_sha1_map: - module_path = module_path.split('.')[-1] + is_user_module = (ModulePath and ModulePath not in ('c', 't') and + (ModulePath in Gen.ModuleSha1Map or + ModulePath in getattr(self.Trans, '_ImportedModules', set()) or + ModulePath in getattr(self.Trans, '_ImportAliases', {}))) + if ModulePath and ModulePath not in ('c', 't') and not is_user_module: + is_user_module = (ModulePath in Gen.ModuleSha1Map or + ModulePath.split('.')[-1] in Gen.ModuleSha1Map or + ModulePath.split('.')[-1] in getattr(self.Trans, '_ImportedModules', set())) + if is_user_module and ModulePath not in Gen.ModuleSha1Map and ModulePath not in getattr(self.Trans, '_ImportedModules', set()): + ModulePath = ModulePath.split('.')[-1] - if module_path and module_path not in ('c', 't') and not is_user_module: + if ModulePath and ModulePath not in ('c', 't') and not is_user_module: return None if is_user_module: - mangled_name = Gen._mangle_func_name(func_name, module_path) - sym_key = f'{module_path}.{func_name}' + mangled_name = Gen._mangle_func_name(func_name, ModulePath) + sym_key = f'{ModulePath}.{func_name}' sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(func_name) is_inline = sym_info and (getattr(sym_info, 'IsInline', False) or isinstance(getattr(sym_info, 'Storage', None), t.CInline)) if is_inline and getattr(sym_info, 'InlineBody', None): @@ -1166,11 +1234,11 @@ class ExprCallHandle(BaseHandle): kw_provided.add(exact_param_names.index(kw.arg)) for i in range(len(exact_param_names)): if i >= provided and i not in kw_provided: - raise Exception(f"调用 {module_path}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值") - elif module_path in Gen.module_sha1_map and len(Node.args) == 0: + raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值") + elif ModulePath in Gen.ModuleSha1Map and len(Node.args) == 0: func = Gen.functions.get(mangled_name) if func and len(func.function_type.args) > 0: - raise Exception(f"调用 {module_path}.{func_name}() 缺少必需参数,函数需要 {len(func.function_type.args)} 个参数但未传入任何参数") + raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数,函数需要 {len(func.function_type.args)} 个参数但未传入任何参数") if Gen._has_function(mangled_name): return self._HandleClosureCallLlvm(Node, mangled_name) try: @@ -1195,7 +1263,7 @@ class ExprCallHandle(BaseHandle): if decl_name != func_name and func_name not in Gen.functions: Gen.functions[func_name] = func_decl return self._HandleClosureCallLlvm(Node, decl_name) - sym_key = f'{module_path}.{func_name}' + sym_key = f'{ModulePath}.{func_name}' sym_info = self.Trans.SymbolTable.get(sym_key) if not sym_info: sym_info = self.Trans.SymbolTable.get(func_name) @@ -1234,9 +1302,13 @@ class ExprCallHandle(BaseHandle): if replaced and replaced != existing: Gen.functions[mangled_name] = replaced return self._HandleClosureCallLlvm(Node, mangled_name) + # 回退: 直接用 func_name 查找(_find_function 会遍历 SHA1 前缀) + fallback_func = Gen._find_function(func_name) + if fallback_func is not None: + return self._HandleClosureCallLlvm(Node, func_name) return None - if module_path == 'c': + if ModulePath == 'c': if func_name == 'Asm': return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node) elif func_name == 'Addr': @@ -1276,7 +1348,7 @@ class ExprCallHandle(BaseHandle): 'GetConsoleOutputCP': (ir.IntType(32), []), 'GetConsoleCP': (ir.IntType(32), []), } - if module_path and 'win32console' in module_path and func_name in win32_apis: + if ModulePath and 'win32console' in ModulePath and func_name in win32_apis: ret_type, param_types = win32_apis[func_name] if func_name not in Gen.functions: func_type = ir.FunctionType(ret_type, param_types) @@ -1304,7 +1376,7 @@ class ExprCallHandle(BaseHandle): if func_name in self._C_LIB_FUNCS: return self._HandleClosureCallLlvm(Node, func_name) - mangled_name = Gen._mangle_func_name(func_name, module_path) + mangled_name = Gen._mangle_func_name(func_name, ModulePath) try: stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(mangled_name, Gen) except Exception: @@ -1322,7 +1394,7 @@ class ExprCallHandle(BaseHandle): Gen.functions[func_name] = func_decl return self._HandleClosureCallLlvm(Node, decl_name) - sym_key = f'{module_path}.{func_name}' if module_path else func_name + sym_key = f'{ModulePath}.{func_name}' if ModulePath else func_name sym_info = self.Trans.SymbolTable.get(sym_key) if not sym_info: sym_info = self.Trans.SymbolTable.get(func_name) @@ -1347,7 +1419,7 @@ class ExprCallHandle(BaseHandle): if isinstance(lp, ir.VoidType): lp = ir.IntType(8).as_pointer() llvm_param_types.append(lp) - mangled_name = Gen._mangle_func_name(func_name, module_path) + mangled_name = Gen._mangle_func_name(func_name, ModulePath) if mangled_name not in Gen.functions: func_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic) func_decl = ir.Function(Gen.module, func_type, name=mangled_name) @@ -1372,18 +1444,22 @@ class ExprCallHandle(BaseHandle): type_info = None try: type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.func) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") if not isinstance(type_info, CTypeInfo): return None target_type_str = type_info.ToString() - is_ptr = type_info.IsPtr - if is_ptr and target_type_str and '*' not in target_type_str: + IsPtr = type_info.IsPtr + if IsPtr and target_type_str and '*' not in target_type_str: target_type_str += ' *' if not target_type_str: return None - if type_info.IsPtr and not is_ptr: - is_ptr = True + if type_info.IsPtr and not IsPtr: + IsPtr = True if '*' not in target_type_str: target_type_str += ' *' if isinstance(type_info.Storage, t.CExport) or isinstance(type_info.Storage, t.CExtern): @@ -1408,8 +1484,8 @@ class ExprCallHandle(BaseHandle): dst_is_float = isinstance(target_type, (ir.FloatType, ir.DoubleType)) src_is_int = isinstance(val.type, ir.IntType) dst_is_int = isinstance(target_type, ir.IntType) - src_is_ptr = isinstance(val.type, ir.PointerType) - dst_is_ptr = isinstance(target_type, ir.PointerType) + src_IsPtr = isinstance(val.type, ir.PointerType) + dst_IsPtr = isinstance(target_type, ir.PointerType) if src_is_int and dst_is_float: is_unsigned = Gen._check_node_unsigned(expr_node) if is_unsigned: @@ -1442,17 +1518,17 @@ class ExprCallHandle(BaseHandle): if isinstance(val.type, ir.DoubleType) and isinstance(target_type, ir.FloatType): return Gen.builder.fptrunc(val, target_type, name="fptrunc_cast") return val - if src_is_ptr and dst_is_int: + if src_IsPtr and dst_is_int: if target_type.width < 64: ptr_to_i64 = Gen.builder.ptrtoint(val, ir.IntType(64), name="ptr2i64") return Gen.builder.trunc(ptr_to_i64, target_type, name="ptr2int_cast") return Gen.builder.ptrtoint(val, target_type, name="ptr2int_cast") - if src_is_int and dst_is_ptr: + if src_is_int and dst_IsPtr: return Gen.builder.inttoptr(val, target_type, name="int2ptr_cast") - if src_is_ptr and dst_is_ptr: + if src_IsPtr and dst_IsPtr: if isinstance(val.type.pointee, ir.PointerType) and isinstance(target_type.pointee, ir.IntType): - loaded = Gen._load(val, name="load_ptr") - return loaded + Loaded = Gen._load(val, name="load_ptr") + return Loaded return Gen.builder.bitcast(val, target_type, name="ptrcast") try: return Gen.builder.bitcast(val, target_type, name="cast") @@ -1464,7 +1540,7 @@ class ExprCallHandle(BaseHandle): if RenumName not in Gen.structs: return None RenumType = Gen.structs[RenumName] - result = Gen._alloca_entry(RenumType, name=f"{RenumName}_{VariantName}") + result = Gen._allocaEntry(RenumType, name=f"{RenumName}_{VariantName}") tag_ptr = Gen.builder.gep(result, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="renum_tag_ptr") Gen._store(ir.Constant(ir.IntType(32), TagValue), tag_ptr) NestedStructName = f"{RenumName}_{VariantName}" @@ -1473,10 +1549,10 @@ class ExprCallHandle(BaseHandle): NestedStructPtrType = ir.PointerType(NestedStructType) variant_ptr = Gen.builder.bitcast(result, NestedStructPtrType, name=f"cast_{NestedStructName}") members = Gen.class_members.get(NestedStructName, []) - payload_members = [(n, t) for n, t in members if n != '__tag'] + payLoad_members = [(n, t) for n, t in members if n != '__tag'] for i, arg in enumerate(Node.args): - if i < len(payload_members): - member_name, member_type = payload_members[i] + if i < len(payLoad_members): + member_name, member_type = payLoad_members[i] ArgVal = self.HandleExprLlvm(arg) if ArgVal: Coerced = Gen._coerce_value(ArgVal, member_type) @@ -1543,7 +1619,7 @@ class ExprCallHandle(BaseHandle): old_var_scopes = list(self.Trans.VarScopes) for param_name, val in saved_vars.items(): if val is not None: - alloca = Gen._alloca_entry(val.type, name=f"inline_arg_{param_name}") + alloca = Gen._allocaEntry(val.type, name=f"inline_arg_{param_name}") Gen._store(val, alloca) self.Trans.VarScopes.append((param_name, alloca)) self.Trans.BodyHandler.HandleBodyLlvm(inline_body) @@ -1679,7 +1755,7 @@ class ExprCallHandle(BaseHandle): CallArgs.append(Gen.variables[var_name]) elif var_name in Gen._reg_values: OldVal = Gen._reg_values[var_name] - var = Gen._alloca_entry(OldVal.type, name=var_name) + var = Gen._allocaEntry(OldVal.type, name=var_name) Gen._store(OldVal, var) Gen.variables[var_name] = var del Gen._reg_values[var_name] @@ -1762,7 +1838,7 @@ class ExprCallHandle(BaseHandle): if target_bits is None: target_bits = 0 is_float = getattr(ctype_inst, 'IsSigned', False) is None and target_bits > 0 if ctype_inst else False - is_ptr_cast = len(Node.args) >= 2 and ( + IsPtr_cast = len(Node.args) >= 2 and ( (isinstance(Node.args[1], ast.Attribute) and Node.args[1].attr == 'CPtr' and isinstance(Node.args[1].value, ast.Name) and Node.args[1].value.id == 't') or (isinstance(Node.args[1], ast.Name) and Node.args[1].id == 'CPtr') ) @@ -1771,10 +1847,10 @@ class ExprCallHandle(BaseHandle): if isinstance(ArgNode, ast.Subscript): SubscriptPtr = self._HandleSubscriptPtrLlvm(ArgNode) if SubscriptPtr: - if MethodName == 'CPtr' or is_ptr_cast: + if MethodName == 'CPtr' or IsPtr_cast: return SubscriptPtr if isinstance(SubscriptPtr.type, ir.PointerType): - val = Gen._load(SubscriptPtr, name="load_subscript_val") + val = Gen._load(SubscriptPtr, name="Load_subscript_val") else: val = SubscriptPtr if target_bits > 0 and isinstance(val.type, ir.IntType) and not is_float: @@ -1784,7 +1860,7 @@ class ExprCallHandle(BaseHandle): val = Gen.builder.trunc(val, ir.IntType(target_bits), name="trunc_cast") return val val = self.HandleExprLlvm(ArgNode) - if is_ptr_cast: + if IsPtr_cast: if target_bits > 0 and not is_float: target_ptr_type = ir.PointerType(ir.IntType(target_bits)) elif is_float and target_bits == 32: @@ -1839,9 +1915,9 @@ class ExprCallHandle(BaseHandle): if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType): return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0) if isinstance(ArgVal.type, ir.IntType): - return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond") + return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond") if isinstance(ArgVal.type, ir.PointerType): - return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond") + return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond") return ir.Constant(ir.IntType(1), 0) elif MethodName in ('CIfdef', 'CIfndef'): return ir.Constant(ir.IntType(1), 1) @@ -1858,8 +1934,12 @@ class ExprCallHandle(BaseHandle): val = self.HandleExprLlvm(arg) if isinstance(val, str): msg = val - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理函数调用失败: {_e}", "Exception") lineno = getattr(Node, 'lineno', 0) raise Exception(f"#error: {msg} (line {lineno})") elif MethodName in ('CElse', 'CEndif', 'CPragma', 'CUndef'): @@ -1877,21 +1957,21 @@ class ExprCallHandle(BaseHandle): if isinstance(var_ptr.type, ir.PointerType) and isinstance(var_ptr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): ObjVal = var_ptr else: - tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp") + tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp") Gen._store(ObjVal, tmp) ObjVal = tmp else: - tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp") + tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp") Gen._store(ObjVal, tmp) ObjVal = tmp else: - tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp") + tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp") Gen._store(ObjVal, tmp) ObjVal = tmp if isinstance(Node.func.value, ast.Name): ModuleName = Node.func.value.id - aliases = getattr(self.Trans, '_import_aliases', {}) - imported = getattr(self.Trans, '_imported_modules', set()) + aliases = getattr(self.Trans, '_ImportAliases', {}) + imported = getattr(self.Trans, '_ImportedModules', set()) actual_module = aliases.get(ModuleName, ModuleName) if ModuleName in imported or actual_module in imported: mangled_name = Gen._mangle_func_name(MethodName, actual_module) @@ -2001,7 +2081,7 @@ class ExprCallHandle(BaseHandle): if not stub_func_type: stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(MethodName, Gen) if not stub_func_type and mangled_name != MethodName: - for sha1 in getattr(Gen, 'module_sha1_map', {}).values(): + for sha1 in getattr(Gen, 'ModuleSha1Map', {}).values(): alt_name = f"{sha1}.{MethodName}" stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(alt_name, Gen) if stub_func_type: @@ -2250,7 +2330,7 @@ class ExprCallHandle(BaseHandle): val = Gen.builder.zext(val, ir.IntType(32), name="zext_bool_print") elif val.type.width == 8: if self._is_char_type(arg): - char_var = Gen._alloca_entry(ir.IntType(8), name="print_char_buf") + char_var = Gen._allocaEntry(ir.IntType(8), name="print_char_buf") Gen.builder.store(val, char_var) fmt_parts.append('%c') fmt_args.append(char_var) @@ -2314,7 +2394,7 @@ class ExprCallHandle(BaseHandle): if ClassName in Gen.structs: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [obj_val], name=f"call_{ClassName}.__str__") - Gen._register_temp_ptr(str_val) + Gen._RegisterTempPtr(str_val) Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) elif isinstance(arg, ast.Name) and arg.id in Gen.var_struct_class: ClassName = Gen.var_struct_class[arg.id] @@ -2325,7 +2405,7 @@ class ExprCallHandle(BaseHandle): if isinstance(obj_val.type, ir.PointerType) and not isinstance(obj_val.type.pointee, type(Gen.structs[ClassName])): obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") str_val = Gen.builder.call(str_func, [obj_val], name=f"call_{ClassName}.__str__") - Gen._register_temp_ptr(str_val) + Gen._RegisterTempPtr(str_val) Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) else: val = self.HandleExprLlvm(arg) @@ -2340,7 +2420,7 @@ class ExprCallHandle(BaseHandle): pointee = val.type.pointee if not self._is_char_pointer(val): try: - val = Gen._load(val, name="print_load") + val = Gen._load(val, name="print_Load") except Exception as _e: if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") @@ -2431,7 +2511,7 @@ class ExprCallHandle(BaseHandle): if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: - result = self.Trans.ExprUtils._try_operator_overload(CN, '__len__', val, Gen) + result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__len__', val, Gen) if result is not None: return result break @@ -2479,8 +2559,12 @@ class ExprCallHandle(BaseHandle): size_bits = getattr(ctype_inst, 'Size', 0) or 0 size_bytes = size_bits // 8 return ir.Constant(ir.IntType(64), size_bytes) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") resolved = CTypeRegistry.ResolveName(type_name) if resolved: ctype_cls, ptr_level = resolved @@ -2491,8 +2575,12 @@ class ExprCallHandle(BaseHandle): if ptr_level > 0: size_bytes = 8 return ir.Constant(ir.IntType(64), size_bytes) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型失败: {_e}", "Exception") return ir.Constant(ir.IntType(64), 0) struct_type = Gen.structs[type_name] @@ -2516,7 +2604,7 @@ class ExprCallHandle(BaseHandle): if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: - result = self.Trans.ExprUtils._try_operator_overload(CN, '__abs__', val, Gen) + result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__abs__', val, Gen) if result is not None: return result break @@ -2562,12 +2650,12 @@ class ExprCallHandle(BaseHandle): if TypeInfo.IsEnum: enum_type_name = arg_name elif isinstance(arg, ast.Attribute): - last_part = None + LastPart = None enum_class_name = None if isinstance(arg.value, ast.Name): - last_part = arg.attr - if last_part in self.Trans.SymbolTable: - AttrInfo = self.Trans.SymbolTable[last_part] + LastPart = arg.attr + if LastPart in self.Trans.SymbolTable: + AttrInfo = self.Trans.SymbolTable[LastPart] if AttrInfo.IsEnumMember and AttrInfo.EnumName: enum_type_name = AttrInfo.EnumName elif isinstance(arg.value, ast.Attribute): @@ -2576,9 +2664,9 @@ class ExprCallHandle(BaseHandle): parts = attr_path.split('.') if len(parts) >= 2: enum_class_name = parts[-2] - last_part = parts[-1] - qualified_name_dot = f"{enum_class_name}.{last_part}" - qualified_name_under = f"{enum_class_name}_{last_part}" + LastPart = parts[-1] + qualified_name_dot = f"{enum_class_name}.{LastPart}" + qualified_name_under = f"{enum_class_name}_{LastPart}" enum_member_found = None for qname in (qualified_name_dot, qualified_name_under): if qname in self.Trans.SymbolTable: @@ -2588,7 +2676,7 @@ class ExprCallHandle(BaseHandle): break if not enum_member_found: for key in self.Trans.SymbolTable: - if key == last_part: + if key == LastPart: info = self.Trans.SymbolTable[key] if info.IsEnumMember and info.EnumName == enum_class_name: enum_member_found = info @@ -2921,7 +3009,7 @@ class ExprCallHandle(BaseHandle): NewFunc = Gen._get_function(NewFuncName) StructType = Gen.structs.get(ClassName) if StructType: - result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca") + result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca") else: return ir.Constant(ir.IntType(32), 0) Gen.builder.call(NewFunc, [result], name=f"before_init_{ClassName}") @@ -2983,7 +3071,7 @@ class ExprCallHandle(BaseHandle): StructType = StructType.pointee is_opaque = isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0) if is_opaque: - result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca") + result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca") Gen.builder.store(ir.Constant(StructType, None), result) InitFunc = Gen.functions.get(InitFuncName) if not InitFunc: @@ -3006,7 +3094,7 @@ class ExprCallHandle(BaseHandle): adjusted_init = Gen._adjust_args(InitArgs, InitFunc) Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") return result - result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca") + result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca") # Call __new__ method if it exists (may replace self with heap pointer) if has_new_method: NewMethodFunc = Gen._find_function(NewMethodFuncName) @@ -3196,7 +3284,7 @@ class ExprCallHandle(BaseHandle): return ptr return None if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): - LoadedValueVal = Gen._load(ValueVal, name="load_subscript") + LoadedValueVal = Gen._load(ValueVal, name="Load_subscript") if isinstance(LoadedValueVal.type, ir.PointerType): ElemPtr = Gen.builder.gep(LoadedValueVal, [IndexVal], name="subscript") return ElemPtr @@ -3232,7 +3320,7 @@ class ExprCallHandle(BaseHandle): IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") return ElemPtr - arr_alloc = Gen._alloca_entry(ValueVal.type, name="arr_subscript_tmp") + arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") Gen._store(ValueVal, arr_alloc) ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") return ElemPtr diff --git a/lib/core/Handles/HandlesExprFormat.py b/lib/core/Handles/HandlesExprFormat.py index 8000bcc..a0ab30b 100644 --- a/lib/core/Handles/HandlesExprFormat.py +++ b/lib/core/Handles/HandlesExprFormat.py @@ -1,110 +1,110 @@ -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 ast -import llvmlite.ir as ir - - -class ExprFormatHandle(BaseHandle): - def _HandleJoinedStrLlvm(self, Node, return_str=False): - Gen = self.Trans.LlvmGen - if not Gen or not Gen.builder: - return ir.Constant(ir.IntType(8).as_pointer(), None) - format_str = "" - cast_args = [] - for part in Node.values: - if isinstance(part, ast.Constant) and isinstance(part.value, str): - format_str += part.value.replace('\\', '\\\\').replace('%', '%%').replace('\n', '\\n').replace('\t', '\\t').replace('\0', '\\0') - elif isinstance(part, ast.FormattedValue): - fmt_class = self.Trans.ExprHandler._get_var_class(part.value, Gen) - if fmt_class and Gen._has_function(f'{fmt_class}.__str__'): - obj_val = self.HandleExprLlvm(part.value) - if obj_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - if fmt_class in Gen.structs: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[fmt_class]), name=f"cast_{fmt_class}") - val = Gen.builder.call(Gen._get_function(f'{fmt_class}.__str__'), [obj_val], name=f"call_{fmt_class}.__str__") - Gen._register_temp_ptr(val) - format_str += "%s" - cast_args.append(val) - else: - format_str += "%s" - cast_args.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) - continue - val = self.HandleExprLlvm(part.value) - if not val: - format_str += "%d" - cast_args.append(ir.Constant(ir.IntType(32), 0)) - continue - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, ir.IntType) and pointee.width == 8: - format_str += "%s" - cast_args.append(val) - elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="fstr_ptr2int") - trunc_val = Gen.builder.trunc(int_val, ir.IntType(32), name="fstr_trunc") - format_str += "%d" - cast_args.append(trunc_val) - else: - loaded = Gen._load(val, name="fstr_deref") - if isinstance(loaded.type, ir.IntType): - if loaded.type.width == 8: - format_str += "%c" - ext = Gen.builder.zext(loaded, ir.IntType(32), name="fstr_char2int") - cast_args.append(ext) - else: - format_str += "%d" - cast_args.append(loaded) - elif isinstance(loaded.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(loaded) - elif isinstance(loaded.type, ir.PointerType): - format_str += "%s" - cast_args.append(loaded) - else: - format_str += "%d" - cast_args.append(loaded) - elif isinstance(val.type, ir.IntType): - if val.type.width == 8: - format_str += "%c" - ext = Gen.builder.zext(val, ir.IntType(32), name="fstr_char2int") - cast_args.append(ext) - elif val.type.width == 1: - zext = Gen.builder.zext(val, ir.IntType(32), name="fstr_bool2int") - format_str += "%d" - cast_args.append(zext) - else: - is_u = Gen._check_node_unsigned(part.value) - format_str += "%u" if is_u else "%d" - cast_args.append(val) - elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(val) - else: - format_str += "%d" - cast_args.append(val) - if not format_str and not cast_args: - return Gen.emit_constant("", 'string') - encoded = format_str.encode('utf-8') + b'\x00' - string_type = ir.ArrayType(ir.IntType(8), len(encoded)) - string_const = ir.Constant(string_type, bytearray(encoded)) - global_var = ir.GlobalVariable(Gen.module, string_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - global_var.initializer = string_const - global_var.linkage = 'internal' - format_ptr = Gen.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) - if return_str: - buf_size = ir.Constant(ir.IntType(64), 1024) - calloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64), ir.IntType(64)]) - calloc_func = Gen._get_or_declare_func('calloc', calloc_type) - buf_ptr = Gen.builder.call(calloc_func, [ir.Constant(ir.IntType(64), 1), buf_size], name="call_calloc_buf") - sprintf_func = Gen.get_or_declare_c_func('sprintf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))], var_arg=True)) - sprintf_args = [buf_ptr, format_ptr] + cast_args - Gen.builder.call(sprintf_func, sprintf_args, name="call_sprintf") - return buf_ptr - printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - call_args = [format_ptr] + cast_args - return Gen.builder.call(printf_func, call_args, name="call_fstring") +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 ast +import llvmlite.ir as ir + + +class ExprFormatHandle(BaseHandle): + def _HandleJoinedStrLlvm(self, Node, return_str=False): + Gen = self.Trans.LlvmGen + if not Gen or not Gen.builder: + return ir.Constant(ir.IntType(8).as_pointer(), None) + format_str = "" + cast_args = [] + for part in Node.values: + if isinstance(part, ast.Constant) and isinstance(part.value, str): + format_str += part.value.replace('\\', '\\\\').replace('%', '%%').replace('\n', '\\n').replace('\t', '\\t').replace('\0', '\\0') + elif isinstance(part, ast.FormattedValue): + fmt_class = self.Trans.ExprHandler._get_var_class(part.value, Gen) + if fmt_class and Gen._has_function(f'{fmt_class}.__str__'): + obj_val = self.HandleExprLlvm(part.value) + if obj_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + if fmt_class in Gen.structs: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[fmt_class]), name=f"cast_{fmt_class}") + val = Gen.builder.call(Gen._get_function(f'{fmt_class}.__str__'), [obj_val], name=f"call_{fmt_class}.__str__") + Gen.RegisterTempPtr(val) + format_str += "%s" + cast_args.append(val) + else: + format_str += "%s" + cast_args.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) + continue + val = self.HandleExprLlvm(part.value) + if not val: + format_str += "%d" + cast_args.append(ir.Constant(ir.IntType(32), 0)) + continue + if isinstance(val.type, ir.PointerType): + pointee = val.type.pointee + if isinstance(pointee, ir.IntType) and pointee.width == 8: + format_str += "%s" + cast_args.append(val) + elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="fstr_ptr2int") + trunc_val = Gen.builder.trunc(int_val, ir.IntType(32), name="fstr_trunc") + format_str += "%d" + cast_args.append(trunc_val) + else: + Loaded = Gen._load(val, name="fstr_deref") + if isinstance(Loaded.type, ir.IntType): + if Loaded.type.width == 8: + format_str += "%c" + ext = Gen.builder.zext(Loaded, ir.IntType(32), name="fstr_char2int") + cast_args.append(ext) + else: + format_str += "%d" + cast_args.append(Loaded) + elif isinstance(Loaded.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(Loaded) + elif isinstance(Loaded.type, ir.PointerType): + format_str += "%s" + cast_args.append(Loaded) + else: + format_str += "%d" + cast_args.append(Loaded) + elif isinstance(val.type, ir.IntType): + if val.type.width == 8: + format_str += "%c" + ext = Gen.builder.zext(val, ir.IntType(32), name="fstr_char2int") + cast_args.append(ext) + elif val.type.width == 1: + zext = Gen.builder.zext(val, ir.IntType(32), name="fstr_bool2int") + format_str += "%d" + cast_args.append(zext) + else: + is_u = Gen._check_node_unsigned(part.value) + format_str += "%u" if is_u else "%d" + cast_args.append(val) + elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(val) + else: + format_str += "%d" + cast_args.append(val) + if not format_str and not cast_args: + return Gen.emit_constant("", 'string') + encoded = format_str.encode('utf-8') + b'\x00' + string_type = ir.ArrayType(ir.IntType(8), len(encoded)) + string_const = ir.Constant(string_type, bytearray(encoded)) + global_var = ir.GlobalVariable(Gen.module, string_type, name=f"str_const_{Gen.string_const_counter}") + Gen.string_const_counter += 1 + global_var.initializer = string_const + global_var.linkage = 'internal' + format_ptr = Gen.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) + if return_str: + buf_size = ir.Constant(ir.IntType(64), 1024) + calloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64), ir.IntType(64)]) + calloc_func = Gen._get_or_declare_func('calloc', calloc_type) + buf_ptr = Gen.builder.call(calloc_func, [ir.Constant(ir.IntType(64), 1), buf_size], name="call_calloc_buf") + sprintf_func = Gen.get_or_declare_c_func('sprintf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))], var_arg=True)) + sprintf_args = [buf_ptr, format_ptr] + cast_args + Gen.builder.call(sprintf_func, sprintf_args, name="call_sprintf") + return buf_ptr + printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) + call_args = [format_ptr] + cast_args + return Gen.builder.call(printf_func, call_args, name="call_fstring") diff --git a/lib/core/Handles/HandlesExprLambda.py b/lib/core/Handles/HandlesExprLambda.py index 9c3309c..a8d8410 100644 --- a/lib/core/Handles/HandlesExprLambda.py +++ b/lib/core/Handles/HandlesExprLambda.py @@ -1,232 +1,232 @@ -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 ast -import llvmlite.ir as ir - - -class ExprLambdaHandle(BaseHandle): - def _HandleLambdaLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not getattr(Gen, '_lambda_counter', None): - Gen._lambda_counter = 0 - lambda_id = Gen._lambda_counter - Gen._lambda_counter += 1 - fn_name = f"lambda_fn_{lambda_id}" - captured_vars = self._get_lambda_captured_vars(Node) - env_types = [] - env_var_names = [] - for var_name, var_val in captured_vars: - env_types.append(var_val.type) - env_var_names.append(var_name) - env_struct_type = ir.LiteralStructType(env_types) if env_types else ir.LiteralStructType([]) - ret_type = self.Trans.ExprUtils._infer_expr_llvm_type_full(Node.body) - param_types = [ir.PointerType(env_struct_type)] - if Node.args: - for arg in Node.args.args: - param_types.append(ir.IntType(32)) - fn_type = ir.FunctionType(ret_type, param_types) - fn = ir.Function(Gen.module, fn_type, name=fn_name) - Gen.functions[fn_name] = fn - entry_block = fn.append_basic_block(name=f"{fn_name}_entry") - prev_builder = Gen.builder - prev_func = Gen.func - prev_vars = dict(Gen.variables) - Gen.builder = ir.IRBuilder(entry_block) - Gen.func = fn - Gen.variables = {} - for i, arg in enumerate(fn.args): - arg.name = f"arg_{i}" if i > 0 else "env" - if env_types: - for idx, var_name in enumerate(env_var_names): - env_ptr = fn.args[0] - zero = ir.Constant(ir.IntType(32), 0) - member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"env_{var_name}") - loaded = Gen._load(member_ptr, name=f"load_env_{var_name}") - temp_alloca = Gen._alloca(loaded.type, name=f"temp_{var_name}") - Gen._store(loaded, temp_alloca) - Gen.variables[var_name] = temp_alloca - if Node.args: - for i, arg in enumerate(Node.args.args): - Gen.variables[arg.arg] = Gen._alloca(ir.IntType(32), name=arg.arg) - Gen._store(fn.args[i + 1], Gen.variables[arg.arg]) - body_val = self.HandleExprLlvm(Node.body) - if body_val: - if isinstance(body_val.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): - body_val = Gen._load(body_val, name="load_lambda_ret") - if body_val.type != ret_type: - if isinstance(body_val.type, ir.IntType) and isinstance(ret_type, ir.IntType): - if body_val.type.width < ret_type.width: - body_val = Gen.builder.zext(body_val, ret_type, name="zext_lambda_ret") - elif body_val.type.width > ret_type.width: - body_val = Gen.builder.trunc(body_val, ret_type, name="trunc_lambda_ret") - elif isinstance(body_val.type, ir.PointerType) and isinstance(ret_type, ir.PointerType): - body_val = Gen.builder.bitcast(body_val, ret_type, name="bitcast_lambda_ret") - Gen.builder.ret(body_val) - else: - Gen.builder.ret(ir.Constant(ret_type, 0)) - Gen.builder = prev_builder - Gen.func = prev_func - Gen.variables = prev_vars - closure_struct_type = ir.LiteralStructType([ - ir.PointerType(ir.IntType(8)), - ir.PointerType(fn_type) - ]) - closure_ptr = Gen._alloca(closure_struct_type, name=f"closure_{lambda_id}") - env_ptr = Gen._alloca(env_struct_type, name=f"env_{lambda_id}") - if env_types: - for idx, (var_name, var_val) in enumerate(captured_vars): - zero = ir.Constant(ir.IntType(32), 0) - member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"store_env_{var_name}") - Gen._store(var_val, member_ptr) - zero = ir.Constant(ir.IntType(32), 0) - env_field_ptr = Gen.builder.gep(closure_ptr, [zero, zero], name="closure_env_ptr") - env_i8_ptr = Gen.builder.bitcast(env_ptr, ir.PointerType(ir.IntType(8)), name="env_i8_ptr") - Gen._store(env_i8_ptr, env_field_ptr) - fn_field_ptr = Gen.builder.gep(closure_ptr, [zero, ir.Constant(ir.IntType(32), 1)], name="closure_fn_ptr") - Gen._store(fn, fn_field_ptr) - return closure_ptr - - def _get_lambda_captured_vars(self, Node): - Gen = self.Trans.LlvmGen - captured = [] - free_vars = self._get_lambda_free_vars(Node) - for var_name in free_vars: - if var_name in Gen.variables: - var_ptr = Gen.variables[var_name] - if isinstance(var_ptr, ir.AllocaInstr) or isinstance(var_ptr, ir.GlobalVariable): - loaded = Gen._load(var_ptr, name=f"capture_{var_name}") - captured.append((var_name, loaded)) - return captured - - def _get_lambda_free_vars(self, Node): - bound_vars = set() - free_vars = set() - # 收集 lambda body 中的 bound 和 free 变量 - self.Trans.ExprUtils._collect_names(Node.body, bound_vars, free_vars) - # lambda 参数也是 bound 的 - if Node.args: - for arg in Node.args.args: - bound_vars.add(arg.arg) - # free 变量 = 在 body 中引用(Load)但不是参数也不是 body 内赋值的变量 - result = free_vars - bound_vars - return list(result) - - def _HandleIfExpLlvm(self, Node): - Gen = self.Trans.LlvmGen - TestVal = self.HandleExprLlvm(Node.test) - if not TestVal: - return None - if not isinstance(TestVal.type, ir.IntType) or TestVal.type.width != 1: - TestVal = Gen.builder.icmp_signed('!=', TestVal, Gen._zero_const(TestVal.type), name="ifexp_cond") - ThenBB = Gen.func.append_basic_block(name="ifexp.then") - ElseBB = Gen.func.append_basic_block(name="ifexp.else") - MergeBB = Gen.func.append_basic_block(name="ifexp.end") - Gen.builder.cbranch(TestVal, ThenBB, ElseBB) - # 先在 ThenBB 中生成 BodyVal - Gen.builder.position_at_start(ThenBB) - BodyVal = self.HandleExprLlvm(Node.body) - if not BodyVal: - BodyVal = ir.Constant(ir.IntType(32), 0) - ThenEndBB = Gen.builder.block - # 在 ElseBB 中生成 OrelseVal - Gen.builder.position_at_start(ElseBB) - OrelseVal = self.HandleExprLlvm(Node.orelse) - if not OrelseVal: - OrelseVal = ir.Constant(ir.IntType(32), 0) - ElseEndBB = Gen.builder.block - # 确定 phi 节点的目标类型 - result_type = BodyVal.type - if BodyVal.type != OrelseVal.type: - if isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.IntType): - result_type = BodyVal.type if BodyVal.type.width >= OrelseVal.type.width else OrelseVal.type - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.PointerType): - # 指针类型,使用 BodyVal 的类型 - result_type = BodyVal.type - elif isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.PointerType): - # BodyVal 是整数,OrelseVal 是指针(字符串字面量) - # 如果指针指向 i8,将指针转换为 i8(加载字符) - if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: - result_type = ir.IntType(8) - else: - result_type = OrelseVal.type - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.IntType): - # BodyVal 是指针(字符串字面量),OrelseVal 是整数 - # 如果指针指向 i8,将指针转换为 i8(加载字符) - if isinstance(BodyVal.type.pointee, ir.IntType) and BodyVal.type.pointee.width == 8: - result_type = ir.IntType(8) - else: - result_type = BodyVal.type - else: - result_type = OrelseVal.type - # 在 ThenBB 末尾添加类型转换(如果需要)和分支 - if not ThenEndBB.is_terminated: - Gen.builder.position_at_end(ThenEndBB) - if BodyVal.type != result_type: - if isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.IntType): - if BodyVal.type.width < result_type.width: - BodyVal = Gen.builder.zext(BodyVal, result_type, name="ifexp_body_zext") - else: - BodyVal = Gen.builder.trunc(BodyVal, result_type, name="ifexp_body_trunc") - elif isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): - # 如果 result_type 是 i8*,说明 Else 分支是字符串字面量 - # 不应该将整数转换为指针,而应该保持整数类型 - # 这里将 result_type 改为 i8 - result_type = ir.IntType(8) - # 重新处理 Else 分支的类型转换 - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): - # 指针转整数 - BodyVal = Gen.builder.ptrtoint(BodyVal, result_type, name="ifexp_body_ptr2int") - Gen.builder.branch(MergeBB) - # 在 ElseBB 末尾添加类型转换(如果需要)和分支 - if not ElseEndBB.is_terminated: - Gen.builder.position_at_end(ElseEndBB) - if OrelseVal.type != result_type: - if isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.IntType): - if OrelseVal.type.width < result_type.width: - OrelseVal = Gen.builder.zext(OrelseVal, result_type, name="ifexp_orelse_zext") - else: - OrelseVal = Gen.builder.trunc(OrelseVal, result_type, name="ifexp_orelse_trunc") - elif isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): - # 如果 result_type 是 i8*,说明 BodyVal 分支是字符串字面量 - # 不应该将整数转换为指针,而应该保持整数类型 - # 这里将 result_type 改为 i8 - result_type = ir.IntType(8) - # 重新处理 BodyVal 分支的类型转换(已经在上面处理过了) - elif isinstance(OrelseVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): - # 如果指针指向 i8,加载字符值 - if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: - OrelseVal = Gen._load(OrelseVal, name="ifexp_orelse_load_char") - else: - OrelseVal = Gen.builder.ptrtoint(OrelseVal, result_type, name="ifexp_orelse_ptr2int") - Gen.builder.branch(MergeBB) - Gen.builder.position_at_start(MergeBB) - result_phi = Gen.builder.phi(result_type, name="ifexp.result") - result_phi.add_incoming(BodyVal, ThenEndBB) - result_phi.add_incoming(OrelseVal, ElseEndBB) - return result_phi - - def _HandleNamedExprLlvm(self, Node): - Gen = self.Trans.LlvmGen - ValueVal = self.HandleExprLlvm(Node.value) - if not ValueVal: - return None - TargetName = Node.target.id - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - if TargetName in Gen.variables and Gen.variables[TargetName] is not None: - VarPtr = Gen.variables[TargetName] - if VarPtr.type.pointee == ValueVal.type: - Gen._store(ValueVal, VarPtr) - else: - NewVar = Gen._alloca(ValueVal.type, name=TargetName) - Gen._store(ValueVal, NewVar) - Gen.variables[TargetName] = NewVar - else: - NewVar = Gen._alloca(ValueVal.type, name=TargetName) - Gen._store(ValueVal, NewVar) - Gen.variables[TargetName] = NewVar - Gen._reg_values[TargetName] = ValueVal - return ValueVal +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 ast +import llvmlite.ir as ir + + +class ExprLambdaHandle(BaseHandle): + def _HandleLambdaLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not getattr(Gen, '_lambda_counter', None): + Gen._lambda_counter = 0 + lambda_id = Gen._lambda_counter + Gen._lambda_counter += 1 + fn_name = f"lambda_fn_{lambda_id}" + captured_vars = self._get_lambda_captured_vars(Node) + env_types = [] + env_var_names = [] + for var_name, var_val in captured_vars: + env_types.append(var_val.type) + env_var_names.append(var_name) + env_struct_type = ir.LiteralStructType(env_types) if env_types else ir.LiteralStructType([]) + ret_type = self.Trans.ExprUtils._infer_expr_llvm_type_full(Node.body) + param_types = [ir.PointerType(env_struct_type)] + if Node.args: + for arg in Node.args.args: + param_types.append(ir.IntType(32)) + fn_type = ir.FunctionType(ret_type, param_types) + fn = ir.Function(Gen.module, fn_type, name=fn_name) + Gen.functions[fn_name] = fn + entry_block = fn.append_basic_block(name=f"{fn_name}_entry") + prev_builder = Gen.builder + prev_func = Gen.func + prev_vars = dict(Gen.variables) + Gen.builder = ir.IRBuilder(entry_block) + Gen.func = fn + Gen.variables = {} + for i, arg in enumerate(fn.args): + arg.name = f"arg_{i}" if i > 0 else "env" + if env_types: + for idx, var_name in enumerate(env_var_names): + env_ptr = fn.args[0] + zero = ir.Constant(ir.IntType(32), 0) + member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"env_{var_name}") + Loaded = Gen._load(member_ptr, name=f"Load_env_{var_name}") + temp_alloca = Gen._alloca(Loaded.type, name=f"temp_{var_name}") + Gen._store(Loaded, temp_alloca) + Gen.variables[var_name] = temp_alloca + if Node.args: + for i, arg in enumerate(Node.args.args): + Gen.variables[arg.arg] = Gen._alloca(ir.IntType(32), name=arg.arg) + Gen._store(fn.args[i + 1], Gen.variables[arg.arg]) + body_val = self.HandleExprLlvm(Node.body) + if body_val: + if isinstance(body_val.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): + body_val = Gen._load(body_val, name="Load_lambda_ret") + if body_val.type != ret_type: + if isinstance(body_val.type, ir.IntType) and isinstance(ret_type, ir.IntType): + if body_val.type.width < ret_type.width: + body_val = Gen.builder.zext(body_val, ret_type, name="zext_lambda_ret") + elif body_val.type.width > ret_type.width: + body_val = Gen.builder.trunc(body_val, ret_type, name="trunc_lambda_ret") + elif isinstance(body_val.type, ir.PointerType) and isinstance(ret_type, ir.PointerType): + body_val = Gen.builder.bitcast(body_val, ret_type, name="bitcast_lambda_ret") + Gen.builder.ret(body_val) + else: + Gen.builder.ret(ir.Constant(ret_type, 0)) + Gen.builder = prev_builder + Gen.func = prev_func + Gen.variables = prev_vars + closure_struct_type = ir.LiteralStructType([ + ir.PointerType(ir.IntType(8)), + ir.PointerType(fn_type) + ]) + closure_ptr = Gen._alloca(closure_struct_type, name=f"closure_{lambda_id}") + env_ptr = Gen._alloca(env_struct_type, name=f"env_{lambda_id}") + if env_types: + for idx, (var_name, var_val) in enumerate(captured_vars): + zero = ir.Constant(ir.IntType(32), 0) + member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"store_env_{var_name}") + Gen._store(var_val, member_ptr) + zero = ir.Constant(ir.IntType(32), 0) + env_field_ptr = Gen.builder.gep(closure_ptr, [zero, zero], name="closure_env_ptr") + env_i8_ptr = Gen.builder.bitcast(env_ptr, ir.PointerType(ir.IntType(8)), name="env_i8_ptr") + Gen._store(env_i8_ptr, env_field_ptr) + fn_field_ptr = Gen.builder.gep(closure_ptr, [zero, ir.Constant(ir.IntType(32), 1)], name="closure_fn_ptr") + Gen._store(fn, fn_field_ptr) + return closure_ptr + + def _get_lambda_captured_vars(self, Node): + Gen = self.Trans.LlvmGen + captured = [] + free_vars = self._get_lambda_free_vars(Node) + for var_name in free_vars: + if var_name in Gen.variables: + var_ptr = Gen.variables[var_name] + if isinstance(var_ptr, ir.AllocaInstr) or isinstance(var_ptr, ir.GlobalVariable): + Loaded = Gen._load(var_ptr, name=f"capture_{var_name}") + captured.append((var_name, Loaded)) + return captured + + def _get_lambda_free_vars(self, Node): + bound_vars = set() + free_vars = set() + # 收集 lambda body 中的 bound 和 free 变量 + self.Trans.ExprUtils._collect_names(Node.body, bound_vars, free_vars) + # lambda 参数也是 bound 的 + if Node.args: + for arg in Node.args.args: + bound_vars.add(arg.arg) + # free 变量 = 在 body 中引用(Load)但不是参数也不是 body 内赋值的变量 + result = free_vars - bound_vars + return list(result) + + def _HandleIfExpLlvm(self, Node): + Gen = self.Trans.LlvmGen + TestVal = self.HandleExprLlvm(Node.test) + if not TestVal: + return None + if not isinstance(TestVal.type, ir.IntType) or TestVal.type.width != 1: + TestVal = Gen.builder.icmp_signed('!=', TestVal, Gen._ZeroConst(TestVal.type), name="ifexp_cond") + ThenBB = Gen.func.append_basic_block(name="ifexp.then") + ElseBB = Gen.func.append_basic_block(name="ifexp.else") + MergeBB = Gen.func.append_basic_block(name="ifexp.end") + Gen.builder.cbranch(TestVal, ThenBB, ElseBB) + # 先在 ThenBB 中生成 BodyVal + Gen.builder.position_at_start(ThenBB) + BodyVal = self.HandleExprLlvm(Node.body) + if not BodyVal: + BodyVal = ir.Constant(ir.IntType(32), 0) + ThenEndBB = Gen.builder.block + # 在 ElseBB 中生成 OrelseVal + Gen.builder.position_at_start(ElseBB) + OrelseVal = self.HandleExprLlvm(Node.orelse) + if not OrelseVal: + OrelseVal = ir.Constant(ir.IntType(32), 0) + ElseEndBB = Gen.builder.block + # 确定 phi 节点的目标类型 + result_type = BodyVal.type + if BodyVal.type != OrelseVal.type: + if isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.IntType): + result_type = BodyVal.type if BodyVal.type.width >= OrelseVal.type.width else OrelseVal.type + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.PointerType): + # 指针类型,使用 BodyVal 的类型 + result_type = BodyVal.type + elif isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.PointerType): + # BodyVal 是整数,OrelseVal 是指针(字符串字面量) + # 如果指针指向 i8,将指针转换为 i8(加载字符) + if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: + result_type = ir.IntType(8) + else: + result_type = OrelseVal.type + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.IntType): + # BodyVal 是指针(字符串字面量),OrelseVal 是整数 + # 如果指针指向 i8,将指针转换为 i8(加载字符) + if isinstance(BodyVal.type.pointee, ir.IntType) and BodyVal.type.pointee.width == 8: + result_type = ir.IntType(8) + else: + result_type = BodyVal.type + else: + result_type = OrelseVal.type + # 在 ThenBB 末尾添加类型转换(如果需要)和分支 + if not ThenEndBB.is_terminated: + Gen.builder.position_at_end(ThenEndBB) + if BodyVal.type != result_type: + if isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.IntType): + if BodyVal.type.width < result_type.width: + BodyVal = Gen.builder.zext(BodyVal, result_type, name="ifexp_body_zext") + else: + BodyVal = Gen.builder.trunc(BodyVal, result_type, name="ifexp_body_trunc") + elif isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): + # 如果 result_type 是 i8*,说明 Else 分支是字符串字面量 + # 不应该将整数转换为指针,而应该保持整数类型 + # 这里将 result_type 改为 i8 + result_type = ir.IntType(8) + # 重新处理 Else 分支的类型转换 + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): + # 指针转整数 + BodyVal = Gen.builder.ptrtoint(BodyVal, result_type, name="ifexp_body_ptr2int") + Gen.builder.branch(MergeBB) + # 在 ElseBB 末尾添加类型转换(如果需要)和分支 + if not ElseEndBB.is_terminated: + Gen.builder.position_at_end(ElseEndBB) + if OrelseVal.type != result_type: + if isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.IntType): + if OrelseVal.type.width < result_type.width: + OrelseVal = Gen.builder.zext(OrelseVal, result_type, name="ifexp_orelse_zext") + else: + OrelseVal = Gen.builder.trunc(OrelseVal, result_type, name="ifexp_orelse_trunc") + elif isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): + # 如果 result_type 是 i8*,说明 BodyVal 分支是字符串字面量 + # 不应该将整数转换为指针,而应该保持整数类型 + # 这里将 result_type 改为 i8 + result_type = ir.IntType(8) + # 重新处理 BodyVal 分支的类型转换(已经在上面处理过了) + elif isinstance(OrelseVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): + # 如果指针指向 i8,加载字符值 + if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: + OrelseVal = Gen._load(OrelseVal, name="ifexp_orelse_Load_char") + else: + OrelseVal = Gen.builder.ptrtoint(OrelseVal, result_type, name="ifexp_orelse_ptr2int") + Gen.builder.branch(MergeBB) + Gen.builder.position_at_start(MergeBB) + result_phi = Gen.builder.phi(result_type, name="ifexp.result") + result_phi.add_incoming(BodyVal, ThenEndBB) + result_phi.add_incoming(OrelseVal, ElseEndBB) + return result_phi + + def _HandleNamedExprLlvm(self, Node): + Gen = self.Trans.LlvmGen + ValueVal = self.HandleExprLlvm(Node.value) + if not ValueVal: + return None + TargetName = Node.target.id + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + if TargetName in Gen.variables and Gen.variables[TargetName] is not None: + VarPtr = Gen.variables[TargetName] + if VarPtr.type.pointee == ValueVal.type: + Gen._store(ValueVal, VarPtr) + else: + NewVar = Gen._alloca(ValueVal.type, name=TargetName) + Gen._store(ValueVal, NewVar) + Gen.variables[TargetName] = NewVar + else: + NewVar = Gen._alloca(ValueVal.type, name=TargetName) + Gen._store(ValueVal, NewVar) + Gen.variables[TargetName] = NewVar + Gen._reg_values[TargetName] = ValueVal + return ValueVal diff --git a/lib/core/Handles/HandlesExprOps.py b/lib/core/Handles/HandlesExprOps.py index 5b061ff..a44c677 100644 --- a/lib/core/Handles/HandlesExprOps.py +++ b/lib/core/Handles/HandlesExprOps.py @@ -1,402 +1,402 @@ -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 ast -import llvmlite.ir as ir - - -class ExprOpsHandle(BaseHandle): - def _HandleBinOpLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - Gen._set_node_info(Node, "BinOp") - LeftVal = self.HandleExprLlvm(Node.left, VarType) - if not LeftVal: - return None - RightVal = self.HandleExprLlvm(Node.right, VarType) - if not RightVal: - return None - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if not Op: - return None - OP_OVERLOAD_MAP = { - '+': '__add__', '-': '__sub__', '*': '__mul__', - '/': '__truediv__', '//': '__floordiv__', '%': '__mod__', - '**': '__pow__', - } - if Op in OP_OVERLOAD_MAP: - LeftClassName = None - if isinstance(LeftVal.type, ir.PointerType): - pointee = LeftVal.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - for CN, ST in Gen.structs.items(): - if pointee == ST: - LeftClassName = CN - break - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - LeftClassName = self.Trans.ExprUtils._get_var_class(Node.left, Gen) - if LeftClassName and LeftClassName in Gen.structs: - TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) - LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") - if LeftClassName is None and isinstance(Node.left, ast.Name): - LeftClassName = Gen.var_struct_class.get(Node.left.id) - if LeftClassName and LeftClassName in Gen.structs: - if isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: - TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) - LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") - if LeftClassName: - op_name = OP_OVERLOAD_MAP[Op] - result = self.Trans.ExprUtils._try_operator_overload(LeftClassName, op_name, LeftVal, Gen, RightVal) - if result is not None: - return result - if Op in ('+', 'Add') and isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: - if isinstance(Node.left, ast.Constant) and isinstance(Node.left.value, str) and len(Node.left.value) == 1: - CharVal = Gen._load(LeftVal, name="load_char_const") - CharAsInt = Gen.builder.zext(CharVal, RightVal.type, name="char_to_int") - result = Gen.builder.add(CharAsInt, RightVal, name="char_add") - TruncResult = Gen.builder.trunc(result, ir.IntType(8), name="add_to_char") - return TruncResult - is_unsigned = Gen._check_node_unsigned(Node.left) or Gen._check_node_unsigned(Node.right) - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.right) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="zext_right") - elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if Op not in ('+', '-', 'Add', 'Sub') and isinstance(LeftVal.type.pointee, ir.IntType): - LeftVal = Gen._load(LeftVal, name="deref_ptr_binop") - if LeftVal.type.width < RightVal.type.width: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_deref_left") - elif LeftVal.type.width > RightVal.type.width: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_deref") - elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): - if Op not in ('+', '-', 'Add', 'Sub') and isinstance(RightVal.type.pointee, ir.IntType): - RightVal = Gen._load(RightVal, name="deref_ptr_binop_r") - if RightVal.type.width < LeftVal.type.width: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right") - elif RightVal.type.width > LeftVal.type.width: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref") - if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name): - vname = Node.left.id - if vname in Gen.var_signedness and Gen.var_signedness[vname]: - is_unsigned = True - result = Gen.emit_binary_op(Op, LeftVal, RightVal, is_unsigned=is_unsigned) - return result - - def _HandleBoolOpLlvm(self, Node): - Gen = self.Trans.LlvmGen - - def _to_bool(val, name): - if isinstance(val.type, (ir.FloatType, ir.DoubleType)): - return Gen.builder.fcmp_ordered('!=', val, ir.Constant(val.type, 0.0), name=name) - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - return Gen.builder.icmp_signed('!=', val, Gen._zero_const(val.type), name=name) - return val - - values = Node.values - if len(values) < 2: - return self.HandleExprLlvm(values[0]) if values else None - if isinstance(Node.op, ast.And): - phi_incomings = [] - end_bb = Gen.func.append_basic_block(name="and.end") - for idx in range(len(values) - 1): - val = self.HandleExprLlvm(values[idx]) - if not val: - if not end_bb.is_terminated: - saved_block = Gen.builder.block - Gen.builder.position_at_start(end_bb) - Gen.builder.unreachable() - Gen.builder.position_at_end(saved_block) - return None - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - val = _to_bool(val, f"andcond{idx}") - cur_bb = Gen.builder.block - next_bb = Gen.func.append_basic_block(name=f"and.rhs{idx}") - Gen.builder.cbranch(val, next_bb, end_bb) - phi_incomings.append((ir.Constant(ir.IntType(1), 0), cur_bb)) - Gen.builder.position_at_start(next_bb) - last_val = self.HandleExprLlvm(values[-1]) - if not last_val: - last_val = ir.Constant(ir.IntType(1), 0) - if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: - last_val = _to_bool(last_val, "andcond_last") - last_bb = Gen.builder.block - Gen.builder.branch(end_bb) - Gen.builder.position_at_start(end_bb) - result_phi = Gen.builder.phi(ir.IntType(1), name="and.result") - for const_val, bb in phi_incomings: - result_phi.add_incoming(const_val, bb) - result_phi.add_incoming(last_val, last_bb) - return result_phi - elif isinstance(Node.op, ast.Or): - phi_incomings = [] - end_bb = Gen.func.append_basic_block(name="or.end") - for idx in range(len(values) - 1): - val = self.HandleExprLlvm(values[idx]) - if not val: - if not end_bb.is_terminated: - saved_block = Gen.builder.block - Gen.builder.position_at_start(end_bb) - Gen.builder.unreachable() - Gen.builder.position_at_end(saved_block) - return None - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - val = _to_bool(val, f"orcond{idx}") - cur_bb = Gen.builder.block - next_bb = Gen.func.append_basic_block(name=f"or.rhs{idx}") - Gen.builder.cbranch(val, end_bb, next_bb) - phi_incomings.append((ir.Constant(ir.IntType(1), 1), cur_bb)) - Gen.builder.position_at_start(next_bb) - last_val = self.HandleExprLlvm(values[-1]) - if not last_val: - last_val = ir.Constant(ir.IntType(1), 1) - if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: - last_val = _to_bool(last_val, "orcond_last") - last_bb = Gen.builder.block - Gen.builder.branch(end_bb) - Gen.builder.position_at_start(end_bb) - result_phi = Gen.builder.phi(ir.IntType(1), name="or.result") - for const_val, bb in phi_incomings: - result_phi.add_incoming(const_val, bb) - result_phi.add_incoming(last_val, last_bb) - return result_phi - return None - - def _HandleUnaryOpLlvm(self, Node): - Gen = self.Trans.LlvmGen - OperandVal = self.HandleExprLlvm(Node.operand) - if not OperandVal: - return None - OpSymbol = self.Trans.ExprHandler.GetUnaryOpSymbol(Node.op) - if not OpSymbol: - return None - UNARY_OVERLOAD_MAP = { - '-': '__neg__', - '+': '__pos__', - '~': '__invert__', - } - if OpSymbol in UNARY_OVERLOAD_MAP: - ClassName = None - if isinstance(OperandVal.type, ir.PointerType): - pointee = OperandVal.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - for CN, ST in Gen.structs.items(): - if pointee == ST: - ClassName = CN - break - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - ClassName = self.Trans.ExprUtils._get_var_class(Node.operand, Gen) - if ClassName and ClassName in Gen.structs: - TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) - OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") - if ClassName is None and isinstance(Node.operand, ast.Name): - ClassName = Gen.var_struct_class.get(Node.operand.id) - if ClassName and ClassName in Gen.structs: - if isinstance(OperandVal.type, ir.PointerType) and isinstance(OperandVal.type.pointee, ir.IntType) and OperandVal.type.pointee.width == 8: - TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) - OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") - if ClassName: - op_name = UNARY_OVERLOAD_MAP[OpSymbol] - result = self.Trans.ExprUtils._try_operator_overload(ClassName, op_name, OperandVal, Gen) - if result is not None: - return result - if OpSymbol == 'not': - if isinstance(OperandVal.type, ir.IntType) and OperandVal.type.width == 1: - return Gen.builder.not_(OperandVal, name="not_result") - if isinstance(OperandVal.type, ir.PointerType): - null_val = ir.Constant(OperandVal.type, None) - return Gen.builder.icmp_signed('==', OperandVal, null_val, name="not_result") - zero = ir.Constant(OperandVal.type, 0) - return Gen.builder.icmp_signed('==', OperandVal, zero, name="not_result") - elif OpSymbol == '~': - if isinstance(OperandVal.type, ir.IntType): - mask = (1 << OperandVal.type.width) - 1 - return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, mask), name="bnot_result") - return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, -1), name="bnot_result") - elif OpSymbol == '+': - return OperandVal - elif OpSymbol == '-': - if isinstance(OperandVal.type, ir.IntType): - return Gen.builder.neg(OperandVal, name="neg_result") - elif isinstance(OperandVal.type, (ir.FloatType, ir.DoubleType)): - return Gen.builder.fneg(OperandVal, name="fneg_result") - return None - - def _HandleCompareLlvm(self, Node): - Gen = self.Trans.LlvmGen - LeftVal = self.HandleExprLlvm(Node.left) - if not LeftVal: - return None - is_unsigned = Gen._check_node_unsigned(Node.left) or (Gen._check_node_unsigned(Node.comparators[0]) if Node.comparators else False) - if len(Node.ops) == 1: - Op = Node.ops[0] - ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) - if not ComparatorSymbol: - return None - RightVal = self.HandleExprLlvm(Node.comparators[0]) - if not RightVal: - return None - if isinstance(LeftVal, ir.Constant) and isinstance(RightVal, ir.Constant): - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - lv, rv = LeftVal.constant, RightVal.constant - lw, rw = LeftVal.type.width, RightVal.type.width - if lw < rw: - lv = lv if lv >= 0 else lv + (1 << lw) - elif rw < lw: - rv = rv if rv >= 0 else rv + (1 << rw) - if is_unsigned: - mask_l = (1 << max(lw, rw)) - 1 - lv = lv & mask_l - rv = rv & mask_l - cmp_map = { - '==': lv == rv, '!=': lv != rv, - '<': lv < rv, '>': lv > rv, - '<=': lv <= rv, '>=': lv >= rv, - } - result = cmp_map.get(ComparatorSymbol, False) - return ir.Constant(ir.IntType(1), 1 if result else 0) - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - # 如果宽类型常量值超出窄类型有符号范围,则必须用zext - # i8 类型默认使用 zext(系统编程中 i8 几乎总是无符号字节) - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max or RightVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_cmp") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left_cmp") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.comparators[0]) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max or LeftVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_cmp") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="sext_right_cmp") - elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8 and isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8: - LeftVal = Gen._load(LeftVal, name="load_char_ptr_cmp") - else: - if isinstance(RightVal, ir.Constant) and RightVal.constant == 0: - RightVal = ir.Constant(LeftVal.type, None) - else: - RightVal = Gen.builder.inttoptr(RightVal, LeftVal.type, name="int2ptr_cmp") - elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): - if isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8 and isinstance(LeftVal.type, ir.IntType) and LeftVal.type.width == 8: - RightVal = Gen._load(RightVal, name="load_char_ptr_cmp") - else: - if isinstance(LeftVal, ir.Constant) and LeftVal.constant == 0: - LeftVal = ir.Constant(RightVal.type, None) - else: - LeftVal = Gen.builder.inttoptr(LeftVal, RightVal.type, name="int2ptr_cmp") - if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType): - result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): - if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): - RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name="int_to_float_cmp") - elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): - LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name="int_to_float_cmp") - result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - elif is_unsigned: - result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - else: - result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - return result - EndBB = Gen.func.append_basic_block(name="cmp.end") - result_val = None - PrevBB = Gen.builder.block - for i, (Op, Comparator) in enumerate(zip(Node.ops, Node.comparators)): - ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) - if not ComparatorSymbol: - continue - RightVal = self.HandleExprLlvm(Comparator) - if not RightVal: - continue - NextBB = Gen.func.append_basic_block(name="cmp.next") - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max or RightVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name=f"zext_left_{i}") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name=f"sext_left_{i}") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Comparator) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max or LeftVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name=f"zext_right_{i}") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name=f"sext_right_{i}") - if is_unsigned: - cmp_result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): - if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): - RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name=f"int_to_float_cmp_{i}") - elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): - LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name=f"int_to_float_cmp_{i}") - cmp_result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - else: - cmp_result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - if result_val is None: - result_val = cmp_result - else: - result_val = Gen.builder.and_(result_val, cmp_result, name=f"and_cmp_{i}") - Gen.builder.cbranch(cmp_result, NextBB, EndBB) - Gen.builder.position_at_start(NextBB) - LeftVal = RightVal - Gen.builder.branch(EndBB) - Gen.builder.position_at_start(EndBB) - final_result = Gen.builder.phi(ir.IntType(1), name="final_cmp") - final_result.add_incoming(ir.Constant(ir.IntType(1), 0), PrevBB) - for i in range(len(Node.ops)): - bb = Gen.func.append_basic_block(name=f"cmp.end.{i}") - final_result.add_incoming(ir.Constant(ir.IntType(1), 1), bb) - return final_result +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 ast +import llvmlite.ir as ir + + +class ExprOpsHandle(BaseHandle): + def _HandleBinOpLlvm(self, Node, VarType=None): + Gen = self.Trans.LlvmGen + Gen._set_node_info(Node, "BinOp") + LeftVal = self.HandleExprLlvm(Node.left, VarType) + if not LeftVal: + return None + RightVal = self.HandleExprLlvm(Node.right, VarType) + if not RightVal: + return None + Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if not Op: + return None + OP_OVERLOAD_MAP = { + '+': '__add__', '-': '__sub__', '*': '__mul__', + '/': '__truediv__', '//': '__floordiv__', '%': '__mod__', + '**': '__pow__', + } + if Op in OP_OVERLOAD_MAP: + LeftClassName = None + if isinstance(LeftVal.type, ir.PointerType): + pointee = LeftVal.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + for CN, ST in Gen.structs.items(): + if pointee == ST: + LeftClassName = CN + break + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + LeftClassName = self.Trans.ExprUtils._get_var_class(Node.left, Gen) + if LeftClassName and LeftClassName in Gen.structs: + TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) + LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") + if LeftClassName is None and isinstance(Node.left, ast.Name): + LeftClassName = Gen.var_struct_class.get(Node.left.id) + if LeftClassName and LeftClassName in Gen.structs: + if isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: + TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) + LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") + if LeftClassName: + op_name = OP_OVERLOAD_MAP[Op] + result = self.Trans.ExprUtils._try_operator_overLoad(LeftClassName, op_name, LeftVal, Gen, RightVal) + if result is not None: + return result + if Op in ('+', 'Add') and isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: + if isinstance(Node.left, ast.Constant) and isinstance(Node.left.value, str) and len(Node.left.value) == 1: + CharVal = Gen._load(LeftVal, name="Load_char_const") + CharAsInt = Gen.builder.zext(CharVal, RightVal.type, name="char_to_int") + result = Gen.builder.add(CharAsInt, RightVal, name="char_add") + TruncResult = Gen.builder.trunc(result, ir.IntType(8), name="add_to_char") + return TruncResult + is_unsigned = Gen._check_node_unsigned(Node.left) or Gen._check_node_unsigned(Node.right) + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.right) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="zext_right") + elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if Op not in ('+', '-', 'Add', 'Sub') and isinstance(LeftVal.type.pointee, ir.IntType): + LeftVal = Gen._load(LeftVal, name="deref_ptr_binop") + if LeftVal.type.width < RightVal.type.width: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_deref_left") + elif LeftVal.type.width > RightVal.type.width: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_deref") + elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): + if Op not in ('+', '-', 'Add', 'Sub') and isinstance(RightVal.type.pointee, ir.IntType): + RightVal = Gen._load(RightVal, name="deref_ptr_binop_r") + if RightVal.type.width < LeftVal.type.width: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right") + elif RightVal.type.width > LeftVal.type.width: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref") + if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name): + vname = Node.left.id + if vname in Gen.var_signedness and Gen.var_signedness[vname]: + is_unsigned = True + result = Gen.emit_binary_op(Op, LeftVal, RightVal, is_unsigned=is_unsigned) + return result + + def _HandleBoolOpLlvm(self, Node): + Gen = self.Trans.LlvmGen + + def _to_bool(val, name): + if isinstance(val.type, (ir.FloatType, ir.DoubleType)): + return Gen.builder.fcmp_ordered('!=', val, ir.Constant(val.type, 0.0), name=name) + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + return Gen.builder.icmp_signed('!=', val, Gen._ZeroConst(val.type), name=name) + return val + + values = Node.values + if len(values) < 2: + return self.HandleExprLlvm(values[0]) if values else None + if isinstance(Node.op, ast.And): + phi_incomings = [] + end_bb = Gen.func.append_basic_block(name="and.end") + for idx in range(len(values) - 1): + val = self.HandleExprLlvm(values[idx]) + if not val: + if not end_bb.is_terminated: + saved_block = Gen.builder.block + Gen.builder.position_at_start(end_bb) + Gen.builder.unreachable() + Gen.builder.position_at_end(saved_block) + return None + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + val = _to_bool(val, f"andcond{idx}") + cur_bb = Gen.builder.block + next_bb = Gen.func.append_basic_block(name=f"and.rhs{idx}") + Gen.builder.cbranch(val, next_bb, end_bb) + phi_incomings.append((ir.Constant(ir.IntType(1), 0), cur_bb)) + Gen.builder.position_at_start(next_bb) + last_val = self.HandleExprLlvm(values[-1]) + if not last_val: + last_val = ir.Constant(ir.IntType(1), 0) + if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: + last_val = _to_bool(last_val, "andcond_last") + last_bb = Gen.builder.block + Gen.builder.branch(end_bb) + Gen.builder.position_at_start(end_bb) + result_phi = Gen.builder.phi(ir.IntType(1), name="and.result") + for const_val, bb in phi_incomings: + result_phi.add_incoming(const_val, bb) + result_phi.add_incoming(last_val, last_bb) + return result_phi + elif isinstance(Node.op, ast.Or): + phi_incomings = [] + end_bb = Gen.func.append_basic_block(name="or.end") + for idx in range(len(values) - 1): + val = self.HandleExprLlvm(values[idx]) + if not val: + if not end_bb.is_terminated: + saved_block = Gen.builder.block + Gen.builder.position_at_start(end_bb) + Gen.builder.unreachable() + Gen.builder.position_at_end(saved_block) + return None + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + val = _to_bool(val, f"orcond{idx}") + cur_bb = Gen.builder.block + next_bb = Gen.func.append_basic_block(name=f"or.rhs{idx}") + Gen.builder.cbranch(val, end_bb, next_bb) + phi_incomings.append((ir.Constant(ir.IntType(1), 1), cur_bb)) + Gen.builder.position_at_start(next_bb) + last_val = self.HandleExprLlvm(values[-1]) + if not last_val: + last_val = ir.Constant(ir.IntType(1), 1) + if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: + last_val = _to_bool(last_val, "orcond_last") + last_bb = Gen.builder.block + Gen.builder.branch(end_bb) + Gen.builder.position_at_start(end_bb) + result_phi = Gen.builder.phi(ir.IntType(1), name="or.result") + for const_val, bb in phi_incomings: + result_phi.add_incoming(const_val, bb) + result_phi.add_incoming(last_val, last_bb) + return result_phi + return None + + def _HandleUnaryOpLlvm(self, Node): + Gen = self.Trans.LlvmGen + OperandVal = self.HandleExprLlvm(Node.operand) + if not OperandVal: + return None + OpSymbol = self.Trans.ExprHandler.GetUnaryOpSymbol(Node.op) + if not OpSymbol: + return None + UNARY_OVERLOAD_MAP = { + '-': '__neg__', + '+': '__pos__', + '~': '__invert__', + } + if OpSymbol in UNARY_OVERLOAD_MAP: + ClassName = None + if isinstance(OperandVal.type, ir.PointerType): + pointee = OperandVal.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + for CN, ST in Gen.structs.items(): + if pointee == ST: + ClassName = CN + break + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + ClassName = self.Trans.ExprUtils._get_var_class(Node.operand, Gen) + if ClassName and ClassName in Gen.structs: + TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) + OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") + if ClassName is None and isinstance(Node.operand, ast.Name): + ClassName = Gen.var_struct_class.get(Node.operand.id) + if ClassName and ClassName in Gen.structs: + if isinstance(OperandVal.type, ir.PointerType) and isinstance(OperandVal.type.pointee, ir.IntType) and OperandVal.type.pointee.width == 8: + TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) + OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") + if ClassName: + op_name = UNARY_OVERLOAD_MAP[OpSymbol] + result = self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, OperandVal, Gen) + if result is not None: + return result + if OpSymbol == 'not': + if isinstance(OperandVal.type, ir.IntType) and OperandVal.type.width == 1: + return Gen.builder.not_(OperandVal, name="not_result") + if isinstance(OperandVal.type, ir.PointerType): + null_val = ir.Constant(OperandVal.type, None) + return Gen.builder.icmp_signed('==', OperandVal, null_val, name="not_result") + zero = ir.Constant(OperandVal.type, 0) + return Gen.builder.icmp_signed('==', OperandVal, zero, name="not_result") + elif OpSymbol == '~': + if isinstance(OperandVal.type, ir.IntType): + mask = (1 << OperandVal.type.width) - 1 + return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, mask), name="bnot_result") + return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, -1), name="bnot_result") + elif OpSymbol == '+': + return OperandVal + elif OpSymbol == '-': + if isinstance(OperandVal.type, ir.IntType): + return Gen.builder.neg(OperandVal, name="neg_result") + elif isinstance(OperandVal.type, (ir.FloatType, ir.DoubleType)): + return Gen.builder.fneg(OperandVal, name="fneg_result") + return None + + def _HandleCompareLlvm(self, Node): + Gen = self.Trans.LlvmGen + LeftVal = self.HandleExprLlvm(Node.left) + if not LeftVal: + return None + is_unsigned = Gen._check_node_unsigned(Node.left) or (Gen._check_node_unsigned(Node.comparators[0]) if Node.comparators else False) + if len(Node.ops) == 1: + Op = Node.ops[0] + ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) + if not ComparatorSymbol: + return None + RightVal = self.HandleExprLlvm(Node.comparators[0]) + if not RightVal: + return None + if isinstance(LeftVal, ir.Constant) and isinstance(RightVal, ir.Constant): + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + lv, rv = LeftVal.constant, RightVal.constant + lw, rw = LeftVal.type.width, RightVal.type.width + if lw < rw: + lv = lv if lv >= 0 else lv + (1 << lw) + elif rw < lw: + rv = rv if rv >= 0 else rv + (1 << rw) + if is_unsigned: + mask_l = (1 << max(lw, rw)) - 1 + lv = lv & mask_l + rv = rv & mask_l + cmp_map = { + '==': lv == rv, '!=': lv != rv, + '<': lv < rv, '>': lv > rv, + '<=': lv <= rv, '>=': lv >= rv, + } + result = cmp_map.get(ComparatorSymbol, False) + return ir.Constant(ir.IntType(1), 1 if result else 0) + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + # 如果宽类型常量值超出窄类型有符号范围,则必须用zext + # i8 类型默认使用 zext(系统编程中 i8 几乎总是无符号字节) + need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max or RightVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_cmp") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left_cmp") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.comparators[0]) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max or LeftVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_cmp") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="sext_right_cmp") + elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8 and isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8: + LeftVal = Gen._load(LeftVal, name="Load_char_ptr_cmp") + else: + if isinstance(RightVal, ir.Constant) and RightVal.constant == 0: + RightVal = ir.Constant(LeftVal.type, None) + else: + RightVal = Gen.builder.inttoptr(RightVal, LeftVal.type, name="int2ptr_cmp") + elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): + if isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8 and isinstance(LeftVal.type, ir.IntType) and LeftVal.type.width == 8: + RightVal = Gen._load(RightVal, name="Load_char_ptr_cmp") + else: + if isinstance(LeftVal, ir.Constant) and LeftVal.constant == 0: + LeftVal = ir.Constant(RightVal.type, None) + else: + LeftVal = Gen.builder.inttoptr(LeftVal, RightVal.type, name="int2ptr_cmp") + if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType): + result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): + if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): + RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name="int_to_float_cmp") + elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): + LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name="int_to_float_cmp") + result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + elif is_unsigned: + result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + else: + result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + return result + EndBB = Gen.func.append_basic_block(name="cmp.end") + result_val = None + PrevBB = Gen.builder.block + for i, (Op, Comparator) in enumerate(zip(Node.ops, Node.comparators)): + ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) + if not ComparatorSymbol: + continue + RightVal = self.HandleExprLlvm(Comparator) + if not RightVal: + continue + NextBB = Gen.func.append_basic_block(name="cmp.next") + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max or RightVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name=f"zext_left_{i}") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name=f"sext_left_{i}") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Comparator) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max or LeftVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name=f"zext_right_{i}") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name=f"sext_right_{i}") + if is_unsigned: + cmp_result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): + if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): + RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name=f"int_to_float_cmp_{i}") + elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): + LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name=f"int_to_float_cmp_{i}") + cmp_result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + else: + cmp_result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + if result_val is None: + result_val = cmp_result + else: + result_val = Gen.builder.and_(result_val, cmp_result, name=f"and_cmp_{i}") + Gen.builder.cbranch(cmp_result, NextBB, EndBB) + Gen.builder.position_at_start(NextBB) + LeftVal = RightVal + Gen.builder.branch(EndBB) + Gen.builder.position_at_start(EndBB) + final_result = Gen.builder.phi(ir.IntType(1), name="final_cmp") + final_result.add_incoming(ir.Constant(ir.IntType(1), 0), PrevBB) + for i in range(len(Node.ops)): + bb = Gen.func.append_basic_block(name=f"cmp.end.{i}") + final_result.add_incoming(ir.Constant(ir.IntType(1), 1), bb) + return final_result diff --git a/lib/core/Handles/HandlesExprUtils.py b/lib/core/Handles/HandlesExprUtils.py index 2dfda20..40db3fe 100644 --- a/lib/core/Handles/HandlesExprUtils.py +++ b/lib/core/Handles/HandlesExprUtils.py @@ -1,240 +1,240 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -import ast -import llvmlite.ir as ir - - -class ExprUtils: - def __init__(self, translator: "Translator"): - self.Trans = translator - - def GetOpSymbol(self, Op): - OpMap = { - ast.Add: '+', ast.Sub: '-', ast.Mult: '*', ast.Div: '/', - ast.FloorDiv: '//', ast.Mod: '%', ast.Pow: '**', ast.BitAnd: '&', - ast.BitOr: '|', ast.BitXor: '^', ast.LShift: '<<', ast.RShift: '>>', - ast.MatMult: '@', - } - return OpMap.get(type(Op), None) - - def GetUnaryOpSymbol(self, Op): - OpMap = {ast.Invert: '~', ast.Not: 'not', ast.UAdd: '+', ast.USub: '-'} - return OpMap.get(type(Op), None) - - def GetComparatorSymbol(self, Op): - OpMap = { - ast.Eq: '==', ast.NotEq: '!=', ast.Lt: '<', ast.LtE: '<=', - ast.Gt: '>', ast.GtE: '>=', ast.Is: 'is', ast.IsNot: 'is not', - ast.In: 'in', ast.NotIn: 'not in', - } - return OpMap.get(type(Op), None) - - def _get_var_class(self, node, Gen): - if isinstance(node, ast.Name): - VarName = node.id - return Gen.var_struct_class.get(VarName) - if isinstance(node, ast.Attribute): - AttrName = node.attr - return Gen.var_struct_class.get(AttrName) - return None - - def _try_operator_overload(self, ClassName, op_name, obj_val, Gen, other_val=None): - FullMethodName = f'{ClassName}.{op_name}' - if not Gen._has_function(FullMethodName): - FullMethodName = f'{ClassName}.{op_name}__' - if Gen._has_function(FullMethodName): - func = Gen._get_function(FullMethodName) - call_args = [obj_val] - if other_val is not None: - call_args.append(other_val) - if len(func.ftype.args) == len(call_args): - for i, (expected_type, actual_val) in enumerate(zip(func.ftype.args, call_args)): - if isinstance(expected_type, ir.PointerType) and isinstance(actual_val.type, ir.PointerType): - if expected_type != actual_val.type: - if isinstance(expected_type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - call_args[i] = Gen.builder.bitcast(actual_val, expected_type, name=f"bitcast_arg_{i}") - result = Gen.builder.call(func, call_args, name=f"call_{FullMethodName}") - return result - return None - - def _llvm_type_to_detailed_string(self, llvm_type, var_name=""): - info = { - 'name': "unknown", - 'size': 0, - 'signed': False, - 'ptr': False - } - if isinstance(llvm_type, ir.IntType): - info['size'] = llvm_type.width // 8 - info['signed'] = True - if llvm_type.width == 8: - info['name'] = "char" - elif llvm_type.width == 16: - info['name'] = "short" - elif llvm_type.width == 32: - info['name'] = "int" - elif llvm_type.width == 64: - info['name'] = "long long" - else: - info['name'] = f"int{llvm_type.width}" - elif isinstance(llvm_type, ir.DoubleType): - info['size'] = 8 - info['signed'] = True - info['name'] = "double" - elif isinstance(llvm_type, ir.FloatType): - info['size'] = 4 - info['signed'] = True - info['name'] = "float" - elif isinstance(llvm_type, ir.PointerType): - info['size'] = 8 - info['signed'] = False - info['ptr'] = True - pointee_info = self._llvm_type_to_detailed_string(llvm_type.pointee) - info['name'] = f"{pointee_info['name']}*" - elif isinstance(llvm_type, (ir.LiteralStructType, ir.IdentifiedStructType)): - size = 0 - for elem in llvm_type.elements: - elem_info = self._llvm_type_to_detailed_string(elem) - size += elem_info['size'] - info['size'] = size - info['signed'] = False - if isinstance(llvm_type, ir.IdentifiedStructType): - info['name'] = llvm_type.name - else: - info['name'] = "struct" - elif isinstance(llvm_type, ir.ArrayType): - elem_info = self._llvm_type_to_detailed_string(llvm_type.element) - info['size'] = elem_info['size'] * llvm_type.count - info['signed'] = elem_info['signed'] - info['name'] = f"{elem_info['name']}[]" - elif isinstance(llvm_type, ir.VoidType): - info['size'] = 0 - info['signed'] = False - info['name'] = "void" - else: - info['size'] = 0 - info['signed'] = False - info['name'] = str(llvm_type) - return info - - def _infer_expr_llvm_type_full(self, node): - Gen = self.Trans.LlvmGen - if isinstance(node, ast.Constant): - if isinstance(node.value, bool): - return ir.IntType(32) - elif isinstance(node.value, int): - return ir.IntType(32) - elif isinstance(node.value, float): - return ir.DoubleType() - elif isinstance(node.value, str): - if getattr(node, 'kind', None) == 'u': - return ir.PointerType(ir.IntType(16)) - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.Name): - if node.id in Gen.variables: - var_ptr = Gen.variables[node.id] - if isinstance(var_ptr.type, ir.PointerType): - return var_ptr.type.pointee - return var_ptr.type - if node.id in Gen._reg_values: - return Gen._reg_values[node.id].type - return ir.IntType(32) - elif isinstance(node, ast.Attribute): - attr_name = node.attr - if attr_name in self.Trans.SymbolTable: - AttrInfo = self.Trans.SymbolTable[attr_name] - if getattr(AttrInfo, 'IsEnumMember', None): - return ir.IntType(32) - return ir.IntType(32) - elif isinstance(node, ast.BinOp): - left_type = self._infer_expr_llvm_type_full(node.left) - right_type = self._infer_expr_llvm_type_full(node.right) - if isinstance(left_type, (ir.FloatType, ir.DoubleType)) or isinstance(right_type, (ir.FloatType, ir.DoubleType)): - return ir.DoubleType() - if isinstance(left_type, ir.PointerType) or isinstance(right_type, ir.PointerType): - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.UnaryOp): - return self._infer_expr_llvm_type_full(node.operand) - elif isinstance(node, ast.Subscript): - val_type = self._infer_expr_llvm_type_full(node.value) - if isinstance(val_type, ir.PointerType): - if isinstance(val_type.pointee, ir.IntType) and val_type.pointee.width == 8: - return ir.IntType(8) - if isinstance(val_type.pointee, ir.ArrayType): - return ir.PointerType(val_type.pointee.element) - return val_type.pointee - if isinstance(val_type, ir.ArrayType): - return val_type.element - if isinstance(val_type, ir.IntType): - return ir.IntType(8) - return ir.IntType(32) - elif isinstance(node, ast.Call): - if isinstance(node.func, ast.Name): - func_name = node.func.id - if Gen._has_function(func_name): - fn = Gen._get_function(func_name) - return fn.function_type.return_type - if func_name == 'len': - return ir.IntType(32) - if func_name == 'sizeof': - return ir.IntType(32) - if func_name == 'ord': - return ir.IntType(32) - if func_name == 'chr': - return ir.IntType(8) - if func_name == 'int': - return ir.IntType(32) - if func_name == 'float' or func_name == 'double': - return ir.DoubleType() - elif isinstance(node.func, ast.Attribute): - if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': - if node.func.attr == 'Deref': - return ir.IntType(64) - if isinstance(node.func.value, ast.Name) and node.func.value.id == 't': - if node.func.attr == 'CChar': - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.Compare): - return ir.IntType(1) - elif isinstance(node, ast.BoolOp): - return ir.IntType(1) - elif isinstance(node, ast.IfExp): - return self._infer_expr_llvm_type_full(node.body) - elif isinstance(node, ast.Attribute): - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - - def _collect_names(self, node, bound, free=None): - """收集 AST 节点中的绑定变量和自由变量 - - Args: - node: AST 节点 - bound: 集合,收集绑定变量(ast.Store 上下文) - free: 集合,收集自由变量(ast.Load 上下文),可为 None - """ - if free is None: - free = set() - if isinstance(node, ast.Name): - if isinstance(node.ctx, ast.Store): - bound.add(node.id) - elif isinstance(node.ctx, ast.Load): - free.add(node.id) - elif isinstance(node, (ast.Lambda, ast.FunctionDef, ast.AsyncFunctionDef)): - # 这些节点有自己的作用域,不递归进入 - # 但需要收集参数名作为 bound - if hasattr(node, 'args') and node.args: - for arg in node.args.args: - bound.add(arg.arg) - elif getattr(node, '_fields', None): - for field in node._fields: - value = getattr(node, field, None) - if isinstance(value, list): - for item in value: - if isinstance(item, (ast.stmt, ast.expr)): - self._collect_names(item, bound, free) - elif isinstance(value, (ast.stmt, ast.expr)): - self._collect_names(value, bound, free) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +import ast +import llvmlite.ir as ir + + +class ExprUtils: + def __init__(self, translator: "Translator"): + self.Trans = translator + + def GetOpSymbol(self, Op): + OpMap = { + ast.Add: '+', ast.Sub: '-', ast.Mult: '*', ast.Div: '/', + ast.FloorDiv: '//', ast.Mod: '%', ast.Pow: '**', ast.BitAnd: '&', + ast.BitOr: '|', ast.BitXor: '^', ast.LShift: '<<', ast.RShift: '>>', + ast.MatMult: '@', + } + return OpMap.get(type(Op), None) + + def GetUnaryOpSymbol(self, Op): + OpMap = {ast.Invert: '~', ast.Not: 'not', ast.UAdd: '+', ast.USub: '-'} + return OpMap.get(type(Op), None) + + def GetComparatorSymbol(self, Op): + OpMap = { + ast.Eq: '==', ast.NotEq: '!=', ast.Lt: '<', ast.LtE: '<=', + ast.Gt: '>', ast.GtE: '>=', ast.Is: 'is', ast.IsNot: 'is not', + ast.In: 'in', ast.NotIn: 'not in', + } + return OpMap.get(type(Op), None) + + def _get_var_class(self, node, Gen): + if isinstance(node, ast.Name): + VarName = node.id + return Gen.var_struct_class.get(VarName) + if isinstance(node, ast.Attribute): + AttrName = node.attr + return Gen.var_struct_class.get(AttrName) + return None + + def _try_operator_overLoad(self, ClassName, op_name, obj_val, Gen, other_val=None): + FullMethodName = f'{ClassName}.{op_name}' + if not Gen._has_function(FullMethodName): + FullMethodName = f'{ClassName}.{op_name}__' + if Gen._has_function(FullMethodName): + func = Gen._get_function(FullMethodName) + call_args = [obj_val] + if other_val is not None: + call_args.append(other_val) + if len(func.ftype.args) == len(call_args): + for i, (expected_type, actual_val) in enumerate(zip(func.ftype.args, call_args)): + if isinstance(expected_type, ir.PointerType) and isinstance(actual_val.type, ir.PointerType): + if expected_type != actual_val.type: + if isinstance(expected_type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + call_args[i] = Gen.builder.bitcast(actual_val, expected_type, name=f"bitcast_arg_{i}") + result = Gen.builder.call(func, call_args, name=f"call_{FullMethodName}") + return result + return None + + def _llvm_type_to_detailed_string(self, llvm_type, var_name=""): + info = { + 'name': "unknown", + 'size': 0, + 'signed': False, + 'ptr': False + } + if isinstance(llvm_type, ir.IntType): + info['size'] = llvm_type.width // 8 + info['signed'] = True + if llvm_type.width == 8: + info['name'] = "char" + elif llvm_type.width == 16: + info['name'] = "short" + elif llvm_type.width == 32: + info['name'] = "int" + elif llvm_type.width == 64: + info['name'] = "long long" + else: + info['name'] = f"int{llvm_type.width}" + elif isinstance(llvm_type, ir.DoubleType): + info['size'] = 8 + info['signed'] = True + info['name'] = "double" + elif isinstance(llvm_type, ir.FloatType): + info['size'] = 4 + info['signed'] = True + info['name'] = "float" + elif isinstance(llvm_type, ir.PointerType): + info['size'] = 8 + info['signed'] = False + info['ptr'] = True + pointee_info = self._llvm_type_to_detailed_string(llvm_type.pointee) + info['name'] = f"{pointee_info['name']}*" + elif isinstance(llvm_type, (ir.LiteralStructType, ir.IdentifiedStructType)): + size = 0 + for elem in llvm_type.elements: + elem_info = self._llvm_type_to_detailed_string(elem) + size += elem_info['size'] + info['size'] = size + info['signed'] = False + if isinstance(llvm_type, ir.IdentifiedStructType): + info['name'] = llvm_type.name + else: + info['name'] = "struct" + elif isinstance(llvm_type, ir.ArrayType): + elem_info = self._llvm_type_to_detailed_string(llvm_type.element) + info['size'] = elem_info['size'] * llvm_type.count + info['signed'] = elem_info['signed'] + info['name'] = f"{elem_info['name']}[]" + elif isinstance(llvm_type, ir.VoidType): + info['size'] = 0 + info['signed'] = False + info['name'] = "void" + else: + info['size'] = 0 + info['signed'] = False + info['name'] = str(llvm_type) + return info + + def _infer_expr_llvm_type_full(self, node): + Gen = self.Trans.LlvmGen + if isinstance(node, ast.Constant): + if isinstance(node.value, bool): + return ir.IntType(32) + elif isinstance(node.value, int): + return ir.IntType(32) + elif isinstance(node.value, float): + return ir.DoubleType() + elif isinstance(node.value, str): + if getattr(node, 'kind', None) == 'u': + return ir.PointerType(ir.IntType(16)) + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.Name): + if node.id in Gen.variables: + var_ptr = Gen.variables[node.id] + if isinstance(var_ptr.type, ir.PointerType): + return var_ptr.type.pointee + return var_ptr.type + if node.id in Gen._reg_values: + return Gen._reg_values[node.id].type + return ir.IntType(32) + elif isinstance(node, ast.Attribute): + attr_name = node.attr + if attr_name in self.Trans.SymbolTable: + AttrInfo = self.Trans.SymbolTable[attr_name] + if getattr(AttrInfo, 'IsEnumMember', None): + return ir.IntType(32) + return ir.IntType(32) + elif isinstance(node, ast.BinOp): + left_type = self._infer_expr_llvm_type_full(node.left) + right_type = self._infer_expr_llvm_type_full(node.right) + if isinstance(left_type, (ir.FloatType, ir.DoubleType)) or isinstance(right_type, (ir.FloatType, ir.DoubleType)): + return ir.DoubleType() + if isinstance(left_type, ir.PointerType) or isinstance(right_type, ir.PointerType): + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.UnaryOp): + return self._infer_expr_llvm_type_full(node.operand) + elif isinstance(node, ast.Subscript): + val_type = self._infer_expr_llvm_type_full(node.value) + if isinstance(val_type, ir.PointerType): + if isinstance(val_type.pointee, ir.IntType) and val_type.pointee.width == 8: + return ir.IntType(8) + if isinstance(val_type.pointee, ir.ArrayType): + return ir.PointerType(val_type.pointee.element) + return val_type.pointee + if isinstance(val_type, ir.ArrayType): + return val_type.element + if isinstance(val_type, ir.IntType): + return ir.IntType(8) + return ir.IntType(32) + elif isinstance(node, ast.Call): + if isinstance(node.func, ast.Name): + func_name = node.func.id + if Gen._has_function(func_name): + fn = Gen._get_function(func_name) + return fn.function_type.return_type + if func_name == 'len': + return ir.IntType(32) + if func_name == 'sizeof': + return ir.IntType(32) + if func_name == 'ord': + return ir.IntType(32) + if func_name == 'chr': + return ir.IntType(8) + if func_name == 'int': + return ir.IntType(32) + if func_name == 'float' or func_name == 'double': + return ir.DoubleType() + elif isinstance(node.func, ast.Attribute): + if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': + if node.func.attr == 'Deref': + return ir.IntType(64) + if isinstance(node.func.value, ast.Name) and node.func.value.id == 't': + if node.func.attr == 'CChar': + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.Compare): + return ir.IntType(1) + elif isinstance(node, ast.BoolOp): + return ir.IntType(1) + elif isinstance(node, ast.IfExp): + return self._infer_expr_llvm_type_full(node.body) + elif isinstance(node, ast.Attribute): + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + + def _collect_names(self, node, bound, free=None): + """收集 AST 节点中的绑定变量和自由变量 + + Args: + node: AST 节点 + bound: 集合,收集绑定变量(ast.Store 上下文) + free: 集合,收集自由变量(ast.Load 上下文),可为 None + """ + if free is None: + free = set() + if isinstance(node, ast.Name): + if isinstance(node.ctx, ast.Store): + bound.add(node.id) + elif isinstance(node.ctx, ast.Load): + free.add(node.id) + elif isinstance(node, (ast.Lambda, ast.FunctionDef, ast.AsyncFunctionDef)): + # 这些节点有自己的作用域,不递归进入 + # 但需要收集参数名作为 bound + if hasattr(node, 'args') and node.args: + for arg in node.args.args: + bound.add(arg.arg) + elif getattr(node, '_fields', None): + for field in node._fields: + value = getattr(node, field, None) + if isinstance(value, list): + for item in value: + if isinstance(item, (ast.stmt, ast.expr)): + self._collect_names(item, bound, free) + elif isinstance(value, (ast.stmt, ast.expr)): + self._collect_names(value, bound, free) diff --git a/lib/core/Handles/HandlesFor.py b/lib/core/Handles/HandlesFor.py index f4053a4..19752db 100644 --- a/lib/core/Handles/HandlesFor.py +++ b/lib/core/Handles/HandlesFor.py @@ -65,12 +65,12 @@ class ForHandle(BaseHandle): return if not isinstance(EndVal.type, ir.IntType): if isinstance(EndVal.type, ir.PointerType) and isinstance(EndVal.type.pointee, ir.IntType): - EndVal = Gen._load(EndVal, name="load_end") + EndVal = Gen._load(EndVal, name="Load_end") else: EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="end") if StartVal and not isinstance(StartVal.type, ir.IntType): if isinstance(StartVal.type, ir.PointerType) and isinstance(StartVal.type.pointee, ir.IntType): - StartVal = Gen._load(StartVal, name="load_start") + StartVal = Gen._load(StartVal, name="Load_start") else: StartVal = Gen.builder.ptrtoint(StartVal, ir.IntType(64), name="start") else: @@ -111,7 +111,7 @@ class ForHandle(BaseHandle): if isinstance(LoopVar.type, ir.PointerType) and isinstance(LoopVar.type.pointee, ir.IntType) and LoopVar.type.pointee == EndVal.type and isinstance(EndVal.type, ir.IntType) and StartVal.type == LoopVar.type.pointee and EndVal.type == StartVal.type: Gen._store(StartVal, LoopVar) else: - NewVar = Gen._alloca_entry(EndVal.type, name=TargetName) + NewVar = Gen._allocaEntry(EndVal.type, name=TargetName) if StartVal.type != EndVal.type: if isinstance(EndVal.type, ir.IntType) and isinstance(StartVal.type, ir.IntType): if StartVal.type.width < EndVal.type.width: @@ -122,7 +122,7 @@ class ForHandle(BaseHandle): Gen.variables[TargetName] = NewVar LoopVar = NewVar else: - LoopVar = Gen._alloca_entry(EndVal.type, name=TargetName) + LoopVar = Gen._allocaEntry(EndVal.type, name=TargetName) Gen.variables[TargetName] = LoopVar Gen._store(StartVal, LoopVar) if StepVal and isinstance(StepVal.type, ir.IntType) and isinstance(EndVal.type, ir.IntType): @@ -186,7 +186,7 @@ class ForHandle(BaseHandle): for name in Node.names: if name in Gen._reg_values and name not in Gen.variables: OldVal = Gen._reg_values[name] - var = Gen._alloca_entry(OldVal.type, name=name) + var = Gen._allocaEntry(OldVal.type, name=name) Gen._store(OldVal, var) Gen.variables[name] = var del Gen._reg_values[name] @@ -275,7 +275,7 @@ class ForHandle(BaseHandle): extra_params.append((var_name, var.type)) elif var_name in Gen._reg_values: OldVal = Gen._reg_values[var_name] - var = Gen._alloca_entry(OldVal.type, name=var_name) + var = Gen._allocaEntry(OldVal.type, name=var_name) Gen._store(OldVal, var) Gen.variables[var_name] = var del Gen._reg_values[var_name] @@ -292,7 +292,7 @@ class ForHandle(BaseHandle): Gen.variables[var_name] = found_var extra_params.append((var_name, found_var.type)) else: - var = Gen._alloca_entry(ir.IntType(32), name=var_name) + var = Gen._allocaEntry(ir.IntType(32), name=var_name) Gen.variables[var_name] = var extra_params.append((var_name, var.type)) if extra_params: @@ -334,11 +334,11 @@ class ForHandle(BaseHandle): TargetName = Node.target.id ElemType = ArrPtr.type.pointee.element ArrayCount = ArrPtr.type.pointee.count - IdxVal = Gen._alloca_entry(ir.IntType(32), name=f"arr_idx") + IdxVal = Gen._allocaEntry(ir.IntType(32), name=f"arr_idx") Gen.builder.store(ir.Constant(ir.IntType(32), 0), IdxVal) if TargetName in Gen._reg_values: del Gen._reg_values[TargetName] - LoopVar = Gen._alloca_entry(ElemType, name=TargetName) + LoopVar = Gen._allocaEntry(ElemType, name=TargetName) Gen.variables[TargetName] = LoopVar Gen._store(ir.Constant(ElemType, None), LoopVar) CondBB = Gen.func.append_basic_block(name="arrfor.cond") @@ -383,13 +383,13 @@ class ForHandle(BaseHandle): if not isinstance(Node.target, ast.Name): return TargetName = Node.target.id - Gen._unregister_temp_ptr(StrVal) + Gen._UnregisterTempPtr(StrVal) PtrVal = Gen.builder.alloca(ir.IntType(8).as_pointer(), name=f"str_ptr_copy") Gen.builder.store(StrVal, PtrVal) CharType = ir.IntType(8) if TargetName in Gen._reg_values: del Gen._reg_values[TargetName] - LoopVar = Gen._alloca_entry(CharType, name=TargetName) + LoopVar = Gen._allocaEntry(CharType, name=TargetName) Gen.variables[TargetName] = LoopVar Gen._store(ir.Constant(CharType, 0), LoopVar) CondBB = Gen.func.append_basic_block(name="strfor.cond") @@ -436,21 +436,21 @@ class ForHandle(BaseHandle): IterVal = self.HandleExprLlvm(Node.iter) if not IterVal: return - Gen._unregister_temp_ptr(IterVal) + Gen._UnregisterTempPtr(IterVal) if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: IterVal = Gen.builder.bitcast(IterVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") IterCall = Gen._get_function(f'{ClassName}.__iter__') IterResult = Gen.builder.call(IterCall, [IterVal], name=f"call_{ClassName}.__iter__") - Gen._unregister_temp_ptr(IterResult) + Gen._UnregisterTempPtr(IterResult) if isinstance(IterResult.type, ir.PointerType) and isinstance(IterResult.type.pointee, ir.IntType) and IterResult.type.pointee.width == 8: IterResult = Gen.builder.bitcast(IterResult, ir.PointerType(Gen.structs[ClassName]), name=f"cast_iter_{ClassName}") NextCall = Gen._get_function(f'{ClassName}.__next__') - StopFlagPtr = Gen._alloca_entry(ir.IntType(1), name="stop_iter_flag") + StopFlagPtr = Gen._allocaEntry(ir.IntType(1), name="stop_iter_flag") Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) NextReturnType = NextCall.function_type.return_type if TargetName in Gen._reg_values: del Gen._reg_values[TargetName] - LoopVar = Gen._alloca_entry(NextReturnType, name=TargetName) + LoopVar = Gen._allocaEntry(NextReturnType, name=TargetName) Gen.variables[TargetName] = LoopVar CondBB = Gen.func.append_basic_block(name="iter.cond") BodyBB = Gen.func.append_basic_block(name="iter.body") @@ -469,7 +469,7 @@ class ForHandle(BaseHandle): and isinstance(last_param_type.pointee, ir.PointerType) and isinstance(last_param_type.pointee.pointee, ir.IntType) and last_param_type.pointee.pointee.width == 8): - null_msg = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") + null_msg = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") NextCallArgs.append(null_msg) NextVal = Gen.builder.call(NextCall, NextCallArgs, name=f"call_{ClassName}.__next__") StopFlag = Gen.builder.load(StopFlagPtr, name="stop_flag") diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index e7c0e50..8e27601 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -23,13 +23,16 @@ class FunctionHandle(BaseHandle): elif d.id == 'classmethod': meta |= FuncMeta.CLASS_METHOD elif isinstance(d, ast.Attribute): - if isinstance(d.value, ast.Name) and d.value.id == 'property': - if d.attr == 'setter': - meta |= FuncMeta.PROPERTY_SETTER - elif d.attr == 'getter': - meta |= FuncMeta.PROPERTY_GETTER - elif d.attr == 'deleter': - meta |= FuncMeta.PROPERTY_DELETER + if isinstance(d.value, ast.Name): + # 支持 @property.setter 和 @propname.setter 两种形式 + # @propname.setter 中 propname 是之前用 @property 定义的同名属性 + if d.value.id == 'property' or d.attr in ('setter', 'getter', 'deleter'): + if d.attr == 'setter': + meta |= FuncMeta.PROPERTY_SETTER + elif d.attr == 'getter': + meta |= FuncMeta.PROPERTY_GETTER + elif d.attr == 'deleter': + meta |= FuncMeta.PROPERTY_DELETER return meta def _body_contains_raise(self, body): @@ -189,8 +192,8 @@ class FunctionHandle(BaseHandle): if sym and isinstance(sym, dict): ret_type_str = sym.get('return_type', '') if ret_type_str and ret_type_str != 'int': - is_ptr = sym.get('is_ptr', False) - return (ret_type_str, is_ptr) + IsPtr = sym.get('IsPtr', False) + return (ret_type_str, IsPtr) elif isinstance(val, ast.Constant): if val.value is None: return ('char', True) @@ -204,8 +207,8 @@ class FunctionHandle(BaseHandle): if var_info and isinstance(var_info, dict): var_type = var_info.get('type', '') if var_type and var_type != 'int': - is_ptr = var_info.get('is_ptr', False) - return (var_type, is_ptr) + IsPtr = var_info.get('IsPtr', False) + return (var_type, IsPtr) elif isinstance(val, ast.Subscript): if (isinstance(val.value, ast.Attribute) and isinstance(val.value.value, ast.Name) @@ -264,8 +267,8 @@ class FunctionHandle(BaseHandle): parts = inner.split(',') elem_type_str = parts[0].strip() if elem_type_str and elem_type_str != 'int': - is_ptr = var_info.get('is_ptr', False) - return (elem_type_str, is_ptr) + IsPtr = var_info.get('IsPtr', False) + return (elem_type_str, IsPtr) return None def _GetFunctionSignatureLlvm(self, Node, Gen, ClassName=None, extra_params=None): @@ -368,7 +371,7 @@ class FunctionHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 - if ReturnTypeInfo.IsVoid and not ReturnTypeInfo.IsState: + if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt @@ -762,8 +765,12 @@ class FunctionHandle(BaseHandle): for attr_name in self._pending_llvm_attrs[FuncName]: try: func.attributes.add(attr_name) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"添加函数属性失败: {_e}", "Exception") Gen.functions[MangledName] = func Gen.functions[FuncName] = func except Exception as _e: @@ -820,6 +827,12 @@ class FunctionHandle(BaseHandle): FuncName = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName + # property setter/deleter 使用不同的函数名后缀,避免与 getter 冲突 + func_meta = self._ExtractFuncMeta(Node.decorator_list) + if FuncMeta.PROPERTY_SETTER in func_meta: + FuncName = FuncName + '$set' + elif FuncMeta.PROPERTY_DELETER in func_meta: + FuncName = FuncName + '$del' CReturnTypes = [] IsPtr = False fn_attrs = {} @@ -971,7 +984,7 @@ class FunctionHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 - if ReturnTypeInfo.IsVoid and not ReturnTypeInfo.IsState: + if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt @@ -992,7 +1005,7 @@ class FunctionHandle(BaseHandle): IsMethod = False IsClassMethod = False ResolvedClassName = ClassName - func_meta = self._ExtractFuncMeta(Node.decorator_list) + # func_meta 已在函数开头提取(用于 setter/deleter 函数名后缀) if not ResolvedClassName: for potential_class in Gen.class_methods: if FuncName.startswith(f"{potential_class}."): @@ -1196,21 +1209,33 @@ class FunctionHandle(BaseHandle): if fn_attrs.get(attr_name): try: func.attributes.add(llvm_name) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"添加函数属性失败: {_e}", "Exception") for key in fn_attrs: if key.startswith('llvm.'): llvm_attr_name = key[5:] try: func.attributes.add(llvm_attr_name) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"添加函数属性失败: {_e}", "Exception") if hasattr(self, '_pending_llvm_attrs') and FuncName in self._pending_llvm_attrs: for attr_name in self._pending_llvm_attrs.pop(FuncName): try: func.attributes.add(attr_name) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"添加函数属性失败: {_e}", "Exception") # 记录自定义行为装饰器信息,供 DecoratorPass 使用 if behavior_decorators: if not hasattr(Gen, '_decorated_funcs'): @@ -1272,7 +1297,7 @@ class FunctionHandle(BaseHandle): break else: # 所有参数都存入 alloca,确保循环体中对参数的修改能正确反映 - var = Gen._alloca_entry(param.type, name=param_name) + var = Gen._allocaEntry(param.type, name=param_name) Gen._store(param, var) Gen.variables[param_name] = var if ResolvedClassName and (IsMethod or RawFuncName == '__init__'): @@ -1298,7 +1323,7 @@ class FunctionHandle(BaseHandle): va_list_size = 8 if is_windows else 24 va_list_align = 8 if is_windows else 16 va_list_type = ir.ArrayType(ir.IntType(8), va_list_size) - va_list_alloc = Gen._alloca_entry(va_list_type, name=f"{vararg_name}_va_list", align=va_list_align) + va_list_alloc = Gen._allocaEntry(va_list_type, name=f"{vararg_name}_va_list", align=va_list_align) va_list_ptr = Gen.builder.bitcast(va_list_alloc, ir.IntType(8).as_pointer(), name=f"{vararg_name}_va_list_i8ptr") Gen._variadic_info = { 'vararg_name': vararg_name, @@ -1307,7 +1332,7 @@ class FunctionHandle(BaseHandle): 'va_start_called': False, } if last_param_ptr: - last_param_alloc = Gen._alloca_entry(last_param_ptr.type, name="last_param_copy") + last_param_alloc = Gen._allocaEntry(last_param_ptr.type, name="last_param_copy") Gen.builder.store(last_param_ptr, last_param_alloc) Gen.emit_va_start(va_list_ptr) Gen._variadic_info['va_start_called'] = True @@ -1379,4 +1404,17 @@ class FunctionHandle(BaseHandle): existing.IsInline = True existing.InlineBody = Node.body existing.InlineParams = [arg.arg for arg in Node.args.args] + # property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList + if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: + BasePropKey = f"{ClassName}.{RawFuncName}" if ClassName else RawFuncName + if BasePropKey in self.Trans.SymbolTable: + base_existing = self.Trans.SymbolTable[BasePropKey] + if func_meta != FuncMeta.NONE: + base_existing.MetaList = base_existing.MetaList | func_meta + else: + PropInfo = CTypeInfo() + PropInfo.Name = BasePropKey + PropInfo.IsFunction = True + PropInfo.MetaList = func_meta + self.Trans.SymbolTable[BasePropKey] = PropInfo return func diff --git a/lib/core/Handles/HandlesIf.py b/lib/core/Handles/HandlesIf.py index f11f3d6..3329eb7 100644 --- a/lib/core/Handles/HandlesIf.py +++ b/lib/core/Handles/HandlesIf.py @@ -1,302 +1,302 @@ -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 -import ast - - -class IfHandle(BaseHandle): - def _get_attr_full_name(self, node): - if isinstance(node, ast.Attribute): - parts = [] - cur = node - while isinstance(cur, ast.Attribute): - parts.append(cur.attr) - cur = cur.value - if isinstance(cur, ast.Name): - parts.append(cur.id) - parts.reverse() - return '.'.join(parts) - return None - - def _is_cif_call(self, node): - if isinstance(node, ast.Call): - if isinstance(node.func, ast.Attribute): - if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': - return node.func.attr in ('CIf', 'CIfdef', 'CIfndef') - if isinstance(node.func, ast.Name): - return node.func.id in ('CIf', 'CIfdef', 'CIfndef') - return False - - def _resolve_macro_name(self, arg): - if isinstance(arg, ast.Name): - return arg.id - if isinstance(arg, ast.Constant) and isinstance(arg.value, str): - return arg.value - if isinstance(arg, ast.Attribute): - full_name = self._get_attr_full_name(arg) - if full_name: - return full_name - return None - - def _evaluate_cif_condition(self, node): - if not isinstance(node, ast.Call): - return None - args = node.args - if not args: - return False - if isinstance(node.func, ast.Attribute): - kind = node.func.attr - elif isinstance(node.func, ast.Name): - kind = node.func.id - else: - return None - if kind == 'CIfdef': - name = self._resolve_macro_name(args[0]) - if name is None: - return False - return self._is_macro_defined(name) - elif kind == 'CIfndef': - name = self._resolve_macro_name(args[0]) - if name is None: - return True - return not self._is_macro_defined(name) - elif kind == 'CIf': - return self._eval_const_expr(args[0]) - return None - - def _is_macro_defined(self, name): - Gen = self.Trans.LlvmGen - if hasattr(Gen, '_define_constants') and name in Gen._define_constants: - return True - if name in self.Trans.SymbolTable: - info = self.Trans.SymbolTable[name] - if getattr(info, 'IsDefine', False): - return True - platform_macros = self._get_platform_macros() - return name in platform_macros - - def _get_macro_value(self, name): - Gen = self.Trans.LlvmGen - if hasattr(Gen, '_define_constants') and name in Gen._define_constants: - val = Gen._define_constants[name] - if isinstance(val, (int, float)): - return val - if name in self.Trans.SymbolTable: - info = self.Trans.SymbolTable[name] - if getattr(info, 'IsDefine', False): - val = getattr(info, 'DefineValue', 0) - if isinstance(val, (int, float)): - return val - platform_macros = self._get_platform_macros() - if name in platform_macros: - return platform_macros[name] - return None - - def _get_platform_macros(self): - Gen = self.Trans.LlvmGen - macros = {} - pi = getattr(Gen, '_platform_info', {}) - ptr_size = getattr(Gen, 'ptr_size', 8) - # 根据目标平台设置宏(从三元组推导) - if pi.get('is_windows'): - macros['_WIN32'] = 1 - if not pi.get('is_32bit'): - macros['_WIN64'] = 1 - macros['WIN64'] = 1 - macros['WIN32'] = 1 - if pi.get('is_linux'): - macros['__linux__'] = 1 - if pi.get('is_macos'): - macros['__APPLE__'] = 1 - macros['__MACH__'] = 1 - if pi.get('is_x86_64'): - macros['__x86_64__'] = 1 - macros['__x86_64'] = 1 - macros['_M_X64'] = 1 - elif pi.get('is_arm64'): - macros['__aarch64__'] = 1 - macros['_M_ARM64'] = 1 - if not pi.get('is_32bit') and pi.get('is_linux'): - macros['__LP64__'] = 1 - elif pi.get('is_32bit'): - macros['_ILP32'] = 1 - macros['SIZEOF_VOID_P'] = ptr_size - macros['__SIZEOF_POINTER__'] = ptr_size - macros['NDEBUG'] = 0 - return macros - - def _eval_const_expr(self, node): - if isinstance(node, ast.Constant): - val = node.value - if isinstance(val, bool): - return 1 if val else 0 - if isinstance(val, int): - return val - if isinstance(val, float): - return 1 if val != 0.0 else 0 - return 0 - if isinstance(node, ast.Name): - name = node.id - val = self._get_macro_value(name) - if val is not None: - return val - return None - if isinstance(node, ast.Attribute): - full_key = self._get_attr_full_name(node) - if full_key: - val = self._get_macro_value(full_key) - if val is not None: - return val - short_name = full_key.split('.')[-1] if '.' in full_key else full_key - val = self._get_macro_value(short_name) - if val is not None: - return val - return None - if isinstance(node, ast.UnaryOp): - operand = self._eval_const_expr(node.operand) - if operand is None: - return None - if isinstance(node.op, ast.Not): - return 1 if not operand else 0 - if isinstance(node.op, ast.USub): - return -operand - if isinstance(node.op, ast.Invert): - return ~operand - return None - if isinstance(node, ast.BinOp): - left = self._eval_const_expr(node.left) - right = self._eval_const_expr(node.right) - if left is None or right is None: - return None - try: - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.FloorDiv): - return left // right if right != 0 else 0 - elif isinstance(node.op, ast.Mod): - return left % right if right != 0 else 0 - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node.op, ast.BitXor): - return left ^ right - except Exception: - return None - return None - if isinstance(node, ast.BoolOp): - if isinstance(node.op, ast.And): - for val in node.values: - result = self._eval_const_expr(val) - if result is None: - return None - if not result: - return 0 - return 1 - elif isinstance(node.op, ast.Or): - for val in node.values: - result = self._eval_const_expr(val) - if result is None: - return None - if result: - return 1 - return 0 - if isinstance(node, ast.Compare): - left = self._eval_const_expr(node.left) - if left is None: - return None - for op, comparator in zip(node.ops, node.comparators): - right = self._eval_const_expr(comparator) - if right is None: - return None - if isinstance(op, ast.Eq): - result = left == right - elif isinstance(op, ast.NotEq): - result = left != right - elif isinstance(op, ast.Lt): - result = left < right - elif isinstance(op, ast.LtE): - result = left <= right - elif isinstance(op, ast.Gt): - result = left > right - elif isinstance(op, ast.GtE): - result = left >= right - else: - return None - if not result: - return 0 - return 1 - if isinstance(node, ast.Call): - if self._is_cif_call(node): - return self._evaluate_cif_condition(node) - return None - - def _HandleIfLlvm(self, Node): - Gen = self.Trans.LlvmGen - if self._is_cif_call(Node.test): - compile_time_val = self._evaluate_cif_condition(Node.test) - if compile_time_val is not None: - if compile_time_val: - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - elif Node.orelse: - if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): - self._HandleIfLlvm(Node.orelse[0]) - else: - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - return - Cond = self.Trans.ExprHandler.HandleExprLlvm(Node.test) - if not Cond: - return - is_const = isinstance(Cond, ir.Constant) and isinstance(Cond.type, ir.IntType) and Cond.type.width == 1 - if is_const: - if Cond.constant: - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - elif Node.orelse: - if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): - self._HandleIfLlvm(Node.orelse[0]) - else: - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - return - if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: - ClassName = self.Trans.ExprHandler._get_var_class(Node.test, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__bool__'): - obj_val = Cond - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - Cond = Gen.builder.call(Gen._get_function(f'{ClassName}.__bool__'), [obj_val], name=f"call_{ClassName}.__bool__") - if isinstance(Cond.type, ir.IntType) and Cond.type.width != 1: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._zero_const(Cond.type), name="bool_result") - else: - if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): - Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="ifcond") - else: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._zero_const(Cond.type), name="ifcond") - ThenBB = Gen.func.append_basic_block(name="then") - ElseBB = Gen.func.append_basic_block(name="else") if Node.orelse else None - MergeBB = Gen.func.append_basic_block(name="endif") - if not Gen.builder.block.is_terminated: - Gen.builder.cbranch(Cond, ThenBB, ElseBB if ElseBB else MergeBB) - Gen.builder.position_at_start(ThenBB) - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(MergeBB) - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(MergeBB) - if not MergeBB.is_terminated: - Gen.builder.position_at_start(MergeBB) - else: - Gen.builder.position_at_end(MergeBB) +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 +import ast + + +class IfHandle(BaseHandle): + def _get_attr_full_name(self, node): + if isinstance(node, ast.Attribute): + parts = [] + cur = node + while isinstance(cur, ast.Attribute): + parts.append(cur.attr) + cur = cur.value + if isinstance(cur, ast.Name): + parts.append(cur.id) + parts.reverse() + return '.'.join(parts) + return None + + def _is_cif_call(self, node): + if isinstance(node, ast.Call): + if isinstance(node.func, ast.Attribute): + if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': + return node.func.attr in ('CIf', 'CIfdef', 'CIfndef') + if isinstance(node.func, ast.Name): + return node.func.id in ('CIf', 'CIfdef', 'CIfndef') + return False + + def _resolve_macro_name(self, arg): + if isinstance(arg, ast.Name): + return arg.id + if isinstance(arg, ast.Constant) and isinstance(arg.value, str): + return arg.value + if isinstance(arg, ast.Attribute): + full_name = self._get_attr_full_name(arg) + if full_name: + return full_name + return None + + def _evaluate_cif_condition(self, node): + if not isinstance(node, ast.Call): + return None + args = node.args + if not args: + return False + if isinstance(node.func, ast.Attribute): + kind = node.func.attr + elif isinstance(node.func, ast.Name): + kind = node.func.id + else: + return None + if kind == 'CIfdef': + name = self._resolve_macro_name(args[0]) + if name is None: + return False + return self._is_macro_defined(name) + elif kind == 'CIfndef': + name = self._resolve_macro_name(args[0]) + if name is None: + return True + return not self._is_macro_defined(name) + elif kind == 'CIf': + return self._eval_const_expr(args[0]) + return None + + def _is_macro_defined(self, name): + Gen = self.Trans.LlvmGen + if hasattr(Gen, '_define_constants') and name in Gen._define_constants: + return True + if name in self.Trans.SymbolTable: + info = self.Trans.SymbolTable[name] + if getattr(info, 'IsDefine', False): + return True + platform_macros = self._get_platform_macros() + return name in platform_macros + + def _get_macro_value(self, name): + Gen = self.Trans.LlvmGen + if hasattr(Gen, '_define_constants') and name in Gen._define_constants: + val = Gen._define_constants[name] + if isinstance(val, (int, float)): + return val + if name in self.Trans.SymbolTable: + info = self.Trans.SymbolTable[name] + if getattr(info, 'IsDefine', False): + val = getattr(info, 'DefineValue', 0) + if isinstance(val, (int, float)): + return val + platform_macros = self._get_platform_macros() + if name in platform_macros: + return platform_macros[name] + return None + + def _get_platform_macros(self): + Gen = self.Trans.LlvmGen + macros = {} + pi = getattr(Gen, '_platform_info', {}) + ptr_size = getattr(Gen, 'ptr_size', 8) + # 根据目标平台设置宏(从三元组推导) + if pi.get('is_windows'): + macros['_WIN32'] = 1 + if not pi.get('is_32bit'): + macros['_WIN64'] = 1 + macros['WIN64'] = 1 + macros['WIN32'] = 1 + if pi.get('is_linux'): + macros['__linux__'] = 1 + if pi.get('is_macos'): + macros['__APPLE__'] = 1 + macros['__MACH__'] = 1 + if pi.get('is_x86_64'): + macros['__x86_64__'] = 1 + macros['__x86_64'] = 1 + macros['_M_X64'] = 1 + elif pi.get('is_arm64'): + macros['__aarch64__'] = 1 + macros['_M_ARM64'] = 1 + if not pi.get('is_32bit') and pi.get('is_linux'): + macros['__LP64__'] = 1 + elif pi.get('is_32bit'): + macros['_ILP32'] = 1 + macros['SIZEOF_VOID_P'] = ptr_size + macros['__SIZEOF_POINTER__'] = ptr_size + macros['NDEBUG'] = 0 + return macros + + def _eval_const_expr(self, node): + if isinstance(node, ast.Constant): + val = node.value + if isinstance(val, bool): + return 1 if val else 0 + if isinstance(val, int): + return val + if isinstance(val, float): + return 1 if val != 0.0 else 0 + return 0 + if isinstance(node, ast.Name): + name = node.id + val = self._get_macro_value(name) + if val is not None: + return val + return None + if isinstance(node, ast.Attribute): + full_key = self._get_attr_full_name(node) + if full_key: + val = self._get_macro_value(full_key) + if val is not None: + return val + short_name = full_key.split('.')[-1] if '.' in full_key else full_key + val = self._get_macro_value(short_name) + if val is not None: + return val + return None + if isinstance(node, ast.UnaryOp): + operand = self._eval_const_expr(node.operand) + if operand is None: + return None + if isinstance(node.op, ast.Not): + return 1 if not operand else 0 + if isinstance(node.op, ast.USub): + return -operand + if isinstance(node.op, ast.Invert): + return ~operand + return None + if isinstance(node, ast.BinOp): + left = self._eval_const_expr(node.left) + right = self._eval_const_expr(node.right) + if left is None or right is None: + return None + try: + if isinstance(node.op, ast.Add): + return left + right + elif isinstance(node.op, ast.Sub): + return left - right + elif isinstance(node.op, ast.Mult): + return left * right + elif isinstance(node.op, ast.FloorDiv): + return left // right if right != 0 else 0 + elif isinstance(node.op, ast.Mod): + return left % right if right != 0 else 0 + elif isinstance(node.op, ast.LShift): + return left << right + elif isinstance(node.op, ast.RShift): + return left >> right + elif isinstance(node.op, ast.BitOr): + return left | right + elif isinstance(node.op, ast.BitAnd): + return left & right + elif isinstance(node.op, ast.BitXor): + return left ^ right + except Exception: + return None + return None + if isinstance(node, ast.BoolOp): + if isinstance(node.op, ast.And): + for val in node.values: + result = self._eval_const_expr(val) + if result is None: + return None + if not result: + return 0 + return 1 + elif isinstance(node.op, ast.Or): + for val in node.values: + result = self._eval_const_expr(val) + if result is None: + return None + if result: + return 1 + return 0 + if isinstance(node, ast.Compare): + left = self._eval_const_expr(node.left) + if left is None: + return None + for op, comparator in zip(node.ops, node.comparators): + right = self._eval_const_expr(comparator) + if right is None: + return None + if isinstance(op, ast.Eq): + result = left == right + elif isinstance(op, ast.NotEq): + result = left != right + elif isinstance(op, ast.Lt): + result = left < right + elif isinstance(op, ast.LtE): + result = left <= right + elif isinstance(op, ast.Gt): + result = left > right + elif isinstance(op, ast.GtE): + result = left >= right + else: + return None + if not result: + return 0 + return 1 + if isinstance(node, ast.Call): + if self._is_cif_call(node): + return self._evaluate_cif_condition(node) + return None + + def _HandleIfLlvm(self, Node): + Gen = self.Trans.LlvmGen + if self._is_cif_call(Node.test): + compile_time_val = self._evaluate_cif_condition(Node.test) + if compile_time_val is not None: + if compile_time_val: + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + elif Node.orelse: + if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): + self._HandleIfLlvm(Node.orelse[0]) + else: + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + return + Cond = self.Trans.ExprHandler.HandleExprLlvm(Node.test) + if not Cond: + return + is_const = isinstance(Cond, ir.Constant) and isinstance(Cond.type, ir.IntType) and Cond.type.width == 1 + if is_const: + if Cond.constant: + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + elif Node.orelse: + if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): + self._HandleIfLlvm(Node.orelse[0]) + else: + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + return + if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: + ClassName = self.Trans.ExprHandler._get_var_class(Node.test, Gen) + if ClassName and Gen._has_function(f'{ClassName}.__bool__'): + obj_val = Cond + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + Cond = Gen.builder.call(Gen._get_function(f'{ClassName}.__bool__'), [obj_val], name=f"call_{ClassName}.__bool__") + if isinstance(Cond.type, ir.IntType) and Cond.type.width != 1: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="bool_result") + else: + if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): + Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="ifcond") + else: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="ifcond") + ThenBB = Gen.func.append_basic_block(name="then") + ElseBB = Gen.func.append_basic_block(name="else") if Node.orelse else None + MergeBB = Gen.func.append_basic_block(name="endif") + if not Gen.builder.block.is_terminated: + Gen.builder.cbranch(Cond, ThenBB, ElseBB if ElseBB else MergeBB) + Gen.builder.position_at_start(ThenBB) + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(MergeBB) + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(MergeBB) + if not MergeBB.is_terminated: + Gen.builder.position_at_start(MergeBB) + else: + Gen.builder.position_at_end(MergeBB) diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 620b5a7..86f5b61 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -2,7 +2,7 @@ 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, CTypeInfo, FuncMeta +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta from lib.includes import t import ast import os @@ -13,13 +13,13 @@ import llvmlite.ir as ir class ImportHandle(BaseHandle): _stub_cache = {} _stub_cache_dir = None - _struct_load_cache = {} + _struct_Load_cache = {} _pyi_cache = {} _pyi_cache_dir = None _project_root_cache = None def _reset_file_cache(self): - self._struct_load_cache.clear() + self._struct_Load_cache.clear() def _find_project_root(self): if self._project_root_cache is not None: @@ -43,17 +43,17 @@ class ImportHandle(BaseHandle): return os.getcwd() def _EmitImportDeclarationsLlvm(self, Node, Gen): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - if not getattr(self.Trans, '_import_aliases', None): - self.Trans._import_aliases = {} + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + if not getattr(self.Trans, '_ImportAliases', None): + self.Trans._ImportAliases = {} for alias in Node.names: name = alias.name if name in ('c', 't'): continue - self.Trans._imported_modules.add(name) + self.Trans._ImportedModules.add(name) if alias.asname: - self.Trans._import_aliases[alias.asname] = name + self.Trans._ImportAliases[alias.asname] = name # 同时在符号表中注册模块别名,以便 CTypeInfo.FromNode 能解析 AliasInfo = CTypeInfo() AliasInfo.IsModuleAlias = True @@ -63,7 +63,7 @@ class ImportHandle(BaseHandle): self._EmitModuleDeclarationsLlvm(name, Gen, register_module_name=current_module) def _RegisterFromImportAliases(self, Node, Gen, module): - """Register 'from module import y as z' aliases after module declarations are loaded""" + """Register 'from module import y as z' aliases after module declarations are Loaded""" if not Node.names: return for alias in Node.names: @@ -125,11 +125,11 @@ class ImportHandle(BaseHandle): def _EmitImportFromDeclarationsLlvm(self, Node, Gen): module = Node.module if Node.module else '' if module in ('c', 't'): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - if not getattr(self.Trans, '_import_aliases', None): - self.Trans._import_aliases = {} - self.Trans._imported_modules.add(module) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + if not getattr(self.Trans, '_ImportAliases', None): + self.Trans._ImportAliases = {} + self.Trans._ImportedModules.add(module) if not hasattr(self.Trans, '_t_c_imported_names'): self.Trans._t_c_imported_names = {} for alias in Node.names: @@ -137,10 +137,10 @@ class ImportHandle(BaseHandle): asname = alias.asname or name self.Trans._t_c_imported_names[asname] = (module, name) return - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - if not getattr(self.Trans, '_import_aliases', None): - self.Trans._import_aliases = {} + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + if not getattr(self.Trans, '_ImportAliases', None): + self.Trans._ImportAliases = {} current_module = self._get_current_module_name() if Node.level and Node.level > 0: current_file = getattr(self.Trans, 'CurrentFile', '') or '' @@ -154,20 +154,20 @@ class ImportHandle(BaseHandle): for ext in SearchExtensions: candidate = sub_path_base + ext if os.path.isfile(candidate): - self.Trans._imported_modules.add(module) + self.Trans._ImportedModules.add(module) self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module, register_module_name=current_module) self._RegisterFromImportAliases(Node, Gen, module) return - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) # 尝试完整模块名和短模块名 full_mod_name = f"{current_module}.{module}" if current_module else module - target_sha1 = module_sha1_map.get(full_mod_name) or module_sha1_map.get(module) + target_sha1 = ModuleSha1Map.get(full_mod_name) or ModuleSha1Map.get(module) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - self.Trans._imported_modules.add(module) + self.Trans._ImportedModules.add(module) self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module, register_module_name=current_module) self._RegisterFromImportAliases(Node, Gen, module) return @@ -177,39 +177,39 @@ class ImportHandle(BaseHandle): SearchExtensions = ['.pyi', '.py'] pkg_name = '' if not module: - # When 'from . import name' is used, load the package's __init__ + # When 'from . import name' is used, Load the package's __init__ # to make package-level names (functions, classes, constants) available pkg_name = self._LoadPackageInitForRelativeImport(mod_dir, Gen, current_module) - # Also try to load each alias as a submodule + # Also try to Load each alias as a submodule for alias in Node.names: found_sub = False for ext in SearchExtensions: sub_path = os.path.join(mod_dir, alias.name + ext) if os.path.isfile(sub_path): - self.Trans._imported_modules.add(alias.name) + self.Trans._ImportedModules.add(alias.name) self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=alias.name, register_module_name=current_module) if alias.asname: - self.Trans._import_aliases[alias.asname] = alias.name + self.Trans._ImportAliases[alias.asname] = alias.name found_sub = True break if not found_sub: # SHA1 map fallback for submodule - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - sub_module_path = f"{pkg_name}.{alias.name}" if pkg_name else alias.name - target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + sub_ModulePath = f"{pkg_name}.{alias.name}" if pkg_name else alias.name + target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - self.Trans._imported_modules.add(sub_module_path) + self.Trans._ImportedModules.add(sub_ModulePath) self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=current_module) if alias.asname: - self.Trans._import_aliases[alias.asname] = alias.name + self.Trans._ImportAliases[alias.asname] = alias.name self._RegisterFromImportAliases(Node, Gen, module or pkg_name) return - self.Trans._imported_modules.add(module) + self.Trans._ImportedModules.add(module) self._EmitModuleDeclarationsLlvm(module, Gen, register_module_name=current_module) self._RegisterFromImportAliases(Node, Gen, module) @@ -229,15 +229,15 @@ class ImportHandle(BaseHandle): reexport_names = [] if module_name and module_name != file_module_name and module_name != effective_register: reexport_names.append(module_name) - # When loading a submodule for 'from .xxx import yyy' inside a package's __init__.py, + # When Loading a submodule for 'from .xxx import yyy' inside a package's __init__.py, # re-export functions under the package name so 'pkg.func()' resolves correctly if reexport_package and reexport_package != file_module_name and reexport_package not in reexport_names: reexport_names.append(reexport_package) self._EmitExternalFuncDeclLlvm(node, Gen, source_module_name=file_module_name, register_module_name=effective_register, reexport_module_names=reexport_names if reexport_names else None) elif isinstance(node, ast.AnnAssign): - self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=pyi_path) + self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=pyi_path) elif isinstance(node, ast.Assign): - self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=pyi_path) + self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=pyi_path) elif isinstance(node, ast.ClassDef): if hasattr(node, 'type_params') and node.type_params: if not hasattr(self.Trans.ClassHandler, '_generic_class_templates'): @@ -263,9 +263,9 @@ class ImportHandle(BaseHandle): if os.path.isfile(candidate): actual_module = f"{register_module_name}.{node.module}" if register_module_name else node.module self._RegisterSubModuleSha1(candidate, actual_module, node.module, Gen) - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(actual_module) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(actual_module) for alias in node.names: if alias.name == '*': self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name) @@ -276,16 +276,16 @@ class ImportHandle(BaseHandle): # SHA1 map 回退 if not found_sub: actual_module = f"{register_module_name}.{node.module}" if register_module_name else node.module - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - target_sha1 = module_sha1_map.get(actual_module) or module_sha1_map.get(node.module) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + target_sha1 = ModuleSha1Map.get(actual_module) or ModuleSha1Map.get(node.module) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(actual_module) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(actual_module) for alias in node.names: if alias.name == '*': self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name) @@ -301,10 +301,10 @@ class ImportHandle(BaseHandle): for ext in SearchExtensions: sub_path = os.path.join(mod_dir, alias.name + ext) if os.path.isfile(sub_path): - sub_module_path = f"{register_module_name}.{alias.name}" if register_module_name else alias.name - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(sub_module_path) + sub_ModulePath = f"{register_module_name}.{alias.name}" if register_module_name else alias.name + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(sub_ModulePath) if alias.name == '*': self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name) else: @@ -313,17 +313,17 @@ class ImportHandle(BaseHandle): break # SHA1 map 回退 if not found_alias: - sub_module_path = f"{register_module_name}.{alias.name}" if register_module_name else alias.name - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name) + sub_ModulePath = f"{register_module_name}.{alias.name}" if register_module_name else alias.name + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(sub_module_path) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(sub_ModulePath) if alias.name == '*': self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=reexport_package or module_name) else: @@ -339,52 +339,56 @@ class ImportHandle(BaseHandle): return None def _RegisterSubModuleSha1(self, candidate_path, actual_module, short_module, Gen): - """Register a submodule's SHA1 in module_sha1_map so cross-module class references work""" + """Register a submodule's SHA1 in ModuleSha1Map so cross-module class references work""" try: with open(candidate_path, 'r', encoding='utf-8') as f: sub_content = f.read() sub_sha1 = hashlib.sha1(sub_content.encode('utf-8')).hexdigest()[:16] - if hasattr(Gen, 'module_sha1_map'): - Gen.module_sha1_map[actual_module] = sub_sha1 - if short_module and short_module not in Gen.module_sha1_map: - Gen.module_sha1_map[short_module] = sub_sha1 - except Exception: - pass + if hasattr(Gen, 'ModuleSha1Map'): + Gen.ModuleSha1Map[actual_module] = sub_sha1 + if short_module and short_module not in Gen.ModuleSha1Map: + Gen.ModuleSha1Map[short_module] = sub_sha1 + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") + + def _LoadPackageInitForRelativeImport(self, mod_dir, Gen, register_module_name): + """Load __init__.py from the package directory for 'from . import name' resolution. + This makes package-level names (functions, classes, constants) available. + Returns the package name.""" + pkg_name = os.path.basename(mod_dir) + init_Loaded = False + + # 跳过当前正在编译的文件,避免重复加载导致 class_members 重复 + current_sha1 = getattr(Gen, 'module_sha1', None) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + pkg_sha1 = ModuleSha1Map.get(pkg_name) + if pkg_sha1 and pkg_sha1 == current_sha1: + return pkg_name + + # Try SHA1 map first (correct mangled names from stub) + if pkg_sha1: + temp_dir = getattr(Gen, '_temp_dir', None) + if temp_dir: + sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.pyi") + if os.path.isfile(sha1_pyi): + self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=pkg_name, register_module_name=register_module_name) + init_Loaded = True + + # Fallback: try Loading __init__.py directly from the package directory + if not init_Loaded: + for ext in ['.pyi', '.py']: + init_path = os.path.join(mod_dir, '__init__' + ext) + if os.path.isfile(init_path): + self._LoadModuleDeclarationsFromFile(init_path, Gen, module_name=pkg_name, register_module_name=register_module_name) + init_Loaded = True + break + + return pkg_name - def _LoadPackageInitForRelativeImport(self, mod_dir, Gen, register_module_name): - """Load __init__.py from the package directory for 'from . import name' resolution. - This makes package-level names (functions, classes, constants) available. - Returns the package name.""" - pkg_name = os.path.basename(mod_dir) - init_loaded = False - - # 跳过当前正在编译的文件,避免重复加载导致 class_members 重复 - current_sha1 = getattr(Gen, 'module_sha1', None) - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - pkg_sha1 = module_sha1_map.get(pkg_name) - if pkg_sha1 and pkg_sha1 == current_sha1: - return pkg_name - - # Try SHA1 map first (correct mangled names from stub) - if pkg_sha1: - temp_dir = getattr(Gen, '_temp_dir', None) - if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.pyi") - if os.path.isfile(sha1_pyi): - self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=pkg_name, register_module_name=register_module_name) - init_loaded = True - - # Fallback: try loading __init__.py directly from the package directory - if not init_loaded: - for ext in ['.pyi', '.py']: - init_path = os.path.join(mod_dir, '__init__' + ext) - if os.path.isfile(init_path): - self._LoadModuleDeclarationsFromFile(init_path, Gen, module_name=pkg_name, register_module_name=register_module_name) - init_loaded = True - break - - return pkg_name - def _EmitModuleDeclarationsLlvm(self, module_name, Gen, register_module_name=None): if module_name in ('pyzlib',): source_sig_files = getattr(self.Trans, '_source_module_sig_files', None) @@ -489,10 +493,10 @@ class ImportHandle(BaseHandle): self._EmitExternalFuncDeclLlvm(node, Gen, source_module_name=module_name, register_module_name=effective_register) has_functions_or_classes = True elif isinstance(node, ast.AnnAssign): - self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=FullModulePath) + self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=FullModulePath) has_functions_or_classes = True elif isinstance(node, ast.Assign): - self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, module_path=FullModulePath) + self._EmitExternalGlobalDeclLlvm(node, Gen, module_name=module_name, ModulePath=FullModulePath) has_functions_or_classes = True elif isinstance(node, ast.ClassDef): if hasattr(node, 'type_params') and node.type_params: @@ -520,9 +524,9 @@ class ImportHandle(BaseHandle): if os.path.isfile(candidate): actual_module = f"{module_name}.{node.module}" if module_name else node.module self._RegisterSubModuleSha1(candidate, actual_module, node.module, Gen) - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(actual_module) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(actual_module) for alias in node.names: if alias.name == '*': self._LoadModuleDeclarationsFromFile(candidate, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name) @@ -534,17 +538,17 @@ class ImportHandle(BaseHandle): # SHA1 map 回退:当文件查找失败时,从 SHA1 映射中查找子模块 stub if not found_sub: actual_module = f"{module_name}.{node.module}" if module_name else node.module - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) # 尝试完整模块名和短模块名 - target_sha1 = module_sha1_map.get(actual_module) or module_sha1_map.get(node.module) + target_sha1 = ModuleSha1Map.get(actual_module) or ModuleSha1Map.get(node.module) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(actual_module) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(actual_module) for alias in node.names: if alias.name == '*': self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name) @@ -561,10 +565,10 @@ class ImportHandle(BaseHandle): for ext in SearchExtensions: sub_path = os.path.join(mod_dir, alias.name + ext) if os.path.isfile(sub_path): - sub_module_path = f"{module_name}.{alias.name}" if module_name else alias.name - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(sub_module_path) + sub_ModulePath = f"{module_name}.{alias.name}" if module_name else alias.name + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(sub_ModulePath) if alias.name == '*': self._LoadModuleDeclarationsFromFile(sub_path, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name) else: @@ -574,17 +578,17 @@ class ImportHandle(BaseHandle): break # SHA1 map 回退 if not found_alias: - sub_module_path = f"{module_name}.{alias.name}" if module_name else alias.name - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - target_sha1 = module_sha1_map.get(sub_module_path) or module_sha1_map.get(alias.name) + sub_ModulePath = f"{module_name}.{alias.name}" if module_name else alias.name + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + target_sha1 = ModuleSha1Map.get(sub_ModulePath) or ModuleSha1Map.get(alias.name) if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") if os.path.isfile(sha1_pyi): - if not getattr(self.Trans, '_imported_modules', None): - self.Trans._imported_modules = set() - self.Trans._imported_modules.add(sub_module_path) + if not getattr(self.Trans, '_ImportedModules', None): + self.Trans._ImportedModules = set() + self.Trans._ImportedModules.add(sub_ModulePath) if alias.name == '*': self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module_name, register_module_name=register_module_name, reexport_package=module_name) else: @@ -603,13 +607,13 @@ class ImportHandle(BaseHandle): if module_name: self._LoadDeclarationsFromStubLlvm(module_name, Gen) - def _EmitExternalGlobalDeclLlvm(self, Node, Gen, module_name=None, module_path=None): + def _EmitExternalGlobalDeclLlvm(self, Node, Gen, module_name=None, ModulePath=None): """Emit external global variable declaration from imported module""" if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name): VarName = Node.target.id # 不再跳过 _ 开头的全局变量,跨模块引用需要声明它们 var_type = ir.IntType(32) - is_ptr = False + IsPtr = False is_string_val = False if VarName in Gen.module.globals: existing = Gen.module.globals[VarName] @@ -637,12 +641,12 @@ class ImportHandle(BaseHandle): var_type = ir.ArrayType(elem_type, 0) else: var_type = Gen._ctype_to_llvm(ElemTypeInfo) - is_ptr = False + IsPtr = False else: TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if TypeInfo: var_type = Gen._ctype_to_llvm(TypeInfo) - is_ptr = TypeInfo.IsPtr + IsPtr = TypeInfo.IsPtr elif isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): list_node = None for side in (Node.annotation.left, Node.annotation.right): @@ -665,20 +669,20 @@ class ImportHandle(BaseHandle): var_type = ir.ArrayType(elem_type, 0) else: var_type = Gen._ctype_to_llvm(ElemTypeInfo) - is_ptr = False + IsPtr = False else: TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if TypeInfo: var_type = Gen._ctype_to_llvm(TypeInfo) - is_ptr = TypeInfo.IsPtr + IsPtr = TypeInfo.IsPtr else: TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if TypeInfo: var_type = Gen._ctype_to_llvm(TypeInfo) - is_ptr = TypeInfo.IsPtr + IsPtr = TypeInfo.IsPtr if isinstance(var_type, ir.IdentifiedStructType) and (var_type.elements is None or len(var_type.elements) == 0): var_type = ir.IntType(32) - if Node.value and module_path and is_ptr and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): + if Node.value and ModulePath and IsPtr and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): str_val = Node.value.value + '\x00' str_bytes = str_val.encode('utf-8') arr_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) @@ -743,13 +747,21 @@ class ImportHandle(BaseHandle): if Node.value: DefineValue = self._ExtractConstValue(Node.value) # 注册不带前缀的键名(例如 Z_NO_COMPRESSION) - self._RegisterCDefineSymbol(VarName, DefineValue, Node.lineno, module_path or 'unknown') + self._RegisterCDefineSymbol(VarName, DefineValue, Node.lineno, ModulePath or 'unknown') # 如果提供了模块名,也注册带模块前缀的键名 if module_name: FullName = f"{module_name}.{VarName}" - self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, module_path or 'unknown') + self._RegisterCDefineSymbol(FullName, DefineValue, Node.lineno, ModulePath or 'unknown') return # 不再继续生成 LLVM 全局变量 - + + # t.State 标记的全局变量:只声明不定义(external linkage),避免 DSO/non-DSO 重定义 + if TypeInfo and TypeInfo.IsState: + if VarName not in Gen.module.globals: + gv = ir.GlobalVariable(Gen.module, var_type, name=VarName) + gv.linkage = 'external' + Gen._export_funcs.add(VarName) + return + gv = ir.GlobalVariable(Gen.module, var_type, name=VarName) if Node.value: @@ -768,7 +780,7 @@ class ImportHandle(BaseHandle): if VarName in Gen.module.globals: return gv = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName) - if Node.value and module_path: + if Node.value and ModulePath: InitVal = self._ExtractValue(Node.value, ir.IntType(32), VarName) if InitVal is not None: gv.initializer = InitVal @@ -893,40 +905,40 @@ class ImportHandle(BaseHandle): return self._ExtractConstValue(value_node.args[0]) return None - def _ExtractTypedefOriginalType(self, value_node): - import ast - from lib.includes.t import CTypeRegistry - if isinstance(value_node, ast.Attribute): - if getattr(value_node.value, 'id', None) == 't': - llvm_str = CTypeRegistry.NameToLLVM(value_node.attr) - if llvm_str: - return llvm_str - elif isinstance(value_node, ast.Name): - llvm_str = CTypeRegistry.NameToLLVM(value_node.id) - if llvm_str: - return llvm_str - elif isinstance(value_node, ast.BinOp) and isinstance(value_node.op, ast.BitOr): - left = self._ExtractTypedefOriginalType(value_node.left) - right = self._ExtractTypedefOriginalType(value_node.right) - parts = [] - if left: - parts.append(left) - if right: - parts.append(right) - if parts: - return '|'.join(parts) - elif isinstance(value_node, ast.Call): - if isinstance(value_node.func, ast.Attribute): - if getattr(value_node.func.value, 'id', None) == 't': - llvm_str = CTypeRegistry.NameToLLVM(value_node.func.attr) - if llvm_str: - return llvm_str - elif isinstance(value_node.func, ast.Name): - llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id) - if llvm_str: - return llvm_str - return None - + def _ExtractTypedefOriginalType(self, value_node): + import ast + from lib.includes.t import CTypeRegistry + if isinstance(value_node, ast.Attribute): + if getattr(value_node.value, 'id', None) == 't': + llvm_str = CTypeRegistry.NameToLLVM(value_node.attr) + if llvm_str: + return llvm_str + elif isinstance(value_node, ast.Name): + llvm_str = CTypeRegistry.NameToLLVM(value_node.id) + if llvm_str: + return llvm_str + elif isinstance(value_node, ast.BinOp) and isinstance(value_node.op, ast.BitOr): + left = self._ExtractTypedefOriginalType(value_node.left) + right = self._ExtractTypedefOriginalType(value_node.right) + parts = [] + if left: + parts.append(left) + if right: + parts.append(right) + if parts: + return '|'.join(parts) + elif isinstance(value_node, ast.Call): + if isinstance(value_node.func, ast.Attribute): + if getattr(value_node.func.value, 'id', None) == 't': + llvm_str = CTypeRegistry.NameToLLVM(value_node.func.attr) + if llvm_str: + return llvm_str + elif isinstance(value_node.func, ast.Name): + llvm_str = CTypeRegistry.NameToLLVM(value_node.func.id) + if llvm_str: + return llvm_str + return None + def _RegisterCDefineSymbol(self, FullName, DefineValue, lineno, FilePath): """Register CDefine constant to SymbolTable""" from lib.core.Handles.HandlesBase import CTypeInfo @@ -938,19 +950,19 @@ class ImportHandle(BaseHandle): # 直接添加到 SymbolTable 字典 self.Trans.SymbolTable[FullName] = info - def _check_annotation_for_state(self, annotation) -> bool: - import ast - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'CExtern', 'State'): - return True - if hasattr(annotation, 'value') and isinstance(annotation.value, ast.Name) and annotation.value.id == 't' and annotation.attr == 'State': - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return self._check_annotation_for_state(annotation.left) or self._check_annotation_for_state(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id in ('CExport', 'CExtern', 'State') - return False - + def _check_annotation_for_state(self, annotation) -> bool: + import ast + if isinstance(annotation, ast.Attribute): + if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'CExtern', 'State'): + return True + if hasattr(annotation, 'value') and isinstance(annotation.value, ast.Name) and annotation.value.id == 't' and annotation.attr == 'State': + return True + elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + return self._check_annotation_for_state(annotation.left) or self._check_annotation_for_state(annotation.right) + elif isinstance(annotation, ast.Name): + return annotation.id in ('CExport', 'CExtern', 'State') + return False + def _EmitExternalFuncDeclLlvm(self, Node, Gen, is_class_method=False, source_module_name=None, register_module_name=None, reexport_module_names=None): FuncName = Node.name if Node.returns and self._check_annotation_for_state(Node.returns): @@ -1086,13 +1098,15 @@ class ImportHandle(BaseHandle): elif d.id == 'classmethod': func_meta |= FuncMeta.CLASS_METHOD elif isinstance(d, ast.Attribute): - if isinstance(d.value, ast.Name) and d.value.id == 'property': - if d.attr == 'setter': - func_meta |= FuncMeta.PROPERTY_SETTER - elif d.attr == 'getter': - func_meta |= FuncMeta.PROPERTY_GETTER - elif d.attr == 'deleter': - func_meta |= FuncMeta.PROPERTY_DELETER + if isinstance(d.value, ast.Name): + # 支持 @property.setter 和 @propname.setter 两种形式 + if d.value.id == 'property' or d.attr in ('setter', 'getter', 'deleter'): + if d.attr == 'setter': + func_meta |= FuncMeta.PROPERTY_SETTER + elif d.attr == 'getter': + func_meta |= FuncMeta.PROPERTY_GETTER + elif d.attr == 'deleter': + func_meta |= FuncMeta.PROPERTY_DELETER if FuncName not in self.Trans.SymbolTable: FuncInfo = CTypeInfo() FuncInfo.Name = FuncName @@ -1103,6 +1117,28 @@ class ImportHandle(BaseHandle): existing = self.Trans.SymbolTable[FuncName] if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: existing.MetaList = func_meta + # 同时注册带模块前缀的符号,以便 module.func_name 查找能命中 + if source_module_name and source_module_name not in ('c', 't'): + FullSymKey = f"{source_module_name}.{FuncName}" + if FullSymKey not in self.Trans.SymbolTable: + FullFuncInfo = CTypeInfo() + FullFuncInfo.Name = FullSymKey + FullFuncInfo.IsFunction = True + FullFuncInfo.MetaList = func_meta + self.Trans.SymbolTable[FullSymKey] = FullFuncInfo + # property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList + if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: + BasePropKey = FuncName.replace('$set', '').replace('$del', '') + if BasePropKey in self.Trans.SymbolTable: + base_existing = self.Trans.SymbolTable[BasePropKey] + if func_meta != FuncMeta.NONE: + base_existing.MetaList = base_existing.MetaList | func_meta + else: + PropInfo = CTypeInfo() + PropInfo.Name = BasePropKey + PropInfo.IsFunction = True + PropInfo.MetaList = func_meta + self.Trans.SymbolTable[BasePropKey] = PropInfo if register_module_name and register_module_name != source_module_name: ReexportName = Gen._mangle_func_name(FuncName, module_name=register_module_name) Gen.functions[ReexportName] = func @@ -1207,10 +1243,10 @@ class ImportHandle(BaseHandle): return self._TryLoadStructFromStub(ClassName, Gen) source_sha1 = None - if actual_module_name and hasattr(Gen, 'module_sha1_map') and actual_module_name in Gen.module_sha1_map: - source_sha1 = Gen.module_sha1_map[actual_module_name] - elif module_name and hasattr(Gen, 'module_sha1_map') and module_name in Gen.module_sha1_map: - source_sha1 = Gen.module_sha1_map[module_name] + if actual_module_name and hasattr(Gen, 'ModuleSha1Map') and actual_module_name in Gen.ModuleSha1Map: + source_sha1 = Gen.ModuleSha1Map[actual_module_name] + elif module_name and hasattr(Gen, 'ModuleSha1Map') and module_name in Gen.ModuleSha1Map: + source_sha1 = Gen.ModuleSha1Map[module_name] # Track which module defines this class (for cross-module name mangling) if source_sha1: if not hasattr(Gen, 'class_sha1_map'): @@ -1268,9 +1304,15 @@ class ImportHandle(BaseHandle): is_item_prop_setter = any(isinstance(d, ast.Attribute) and d.attr == 'setter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list) is_item_prop_getter = any(isinstance(d, ast.Attribute) and d.attr == 'getter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list) is_item_prop_deleter = any(isinstance(d, ast.Attribute) and d.attr == 'deleter' and isinstance(d.value, ast.Name) and d.value.id == 'property' for d in item.decorator_list) - if FuncFullName not in Gen.functions: + # setter/deleter 使用不同的函数名后缀 + DeclFuncName = FuncFullName + if is_item_prop_setter: + DeclFuncName = FuncFullName + '$set' + elif is_item_prop_deleter: + DeclFuncName = FuncFullName + '$del' + if DeclFuncName not in Gen.functions: FuncDeclNode = ast.FunctionDef( - name=FuncFullName, + name=DeclFuncName, args=item.args, body=item.body, decorator_list=item.decorator_list, @@ -1290,10 +1332,11 @@ class ImportHandle(BaseHandle): func_meta |= FuncMeta.PROPERTY_GETTER if is_item_prop_deleter: func_meta |= FuncMeta.PROPERTY_DELETER - SymKey = FuncFullName + # setter/deleter 的 SymKey 使用带后缀的函数名 + SymKey = DeclFuncName if SymKey not in self.Trans.SymbolTable: FuncInfo = CTypeInfo() - FuncInfo.Name = FuncFullName + FuncInfo.Name = SymKey FuncInfo.IsFunction = True FuncInfo.MetaList = func_meta self.Trans.SymbolTable[SymKey] = FuncInfo @@ -1301,6 +1344,18 @@ class ImportHandle(BaseHandle): existing = self.Trans.SymbolTable[SymKey] if existing.MetaList == FuncMeta.NONE and func_meta != FuncMeta.NONE: existing.MetaList = func_meta + # setter/deleter: 同时在原始 PropKey(不带后缀)下注册 MetaList + if is_item_prop_setter or is_item_prop_deleter: + if FuncFullName in self.Trans.SymbolTable: + base_existing = self.Trans.SymbolTable[FuncFullName] + if func_meta != FuncMeta.NONE: + base_existing.MetaList = base_existing.MetaList | func_meta + else: + PropInfo = CTypeInfo() + PropInfo.Name = FuncFullName + PropInfo.IsFunction = True + PropInfo.MetaList = func_meta + self.Trans.SymbolTable[FuncFullName] = PropInfo if has_methods: if IsCVTable: Gen._cross_module_vtable_classes.add(ClassName) @@ -1308,8 +1363,8 @@ class ImportHandle(BaseHandle): NewFuncName = f'{ClassName}.__before_init__' if not Gen._has_function(NewFuncName) and (IsCpythonObject or IsCVTable): source_sha1 = None - if module_name and hasattr(Gen, 'module_sha1_map') and module_name in Gen.module_sha1_map: - source_sha1 = Gen.module_sha1_map[module_name] + if module_name and hasattr(Gen, 'ModuleSha1Map') and module_name in Gen.ModuleSha1Map: + source_sha1 = Gen.ModuleSha1Map[module_name] MangledName = Gen._mangle_name(NewFuncName) if not source_sha1 else f"{source_sha1}.{NewFuncName}" StructType = Gen.structs.get(ClassName) if StructType: @@ -1327,9 +1382,9 @@ class ImportHandle(BaseHandle): def _TryLoadStructFromStub(self, class_name: str, Gen): cache_key = class_name - if cache_key in self._struct_load_cache: + if cache_key in self._struct_Load_cache: return - self._struct_load_cache[cache_key] = True + self._struct_Load_cache[cache_key] = True import os, re ProjectRoot = self._find_project_root() @@ -1358,9 +1413,13 @@ class ImportHandle(BaseHandle): self._stub_cache.setdefault(short_name, []).append((full_name, struct_body, source_sha1)) if '.' in full_name: self._stub_cache.setdefault(full_name, []).append((full_name, struct_body, source_sha1)) - except Exception: - pass - + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") + if class_name not in self._stub_cache: return @@ -1380,12 +1439,16 @@ class ImportHandle(BaseHandle): elem_types.append(et if et else ir.IntType(32)) try: st = Gen._get_or_create_struct(class_name, source_sha1=source_sha1, packed=is_packed) - if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): + if isinstance(st, ir.IdentifiedStructType) and st.is_opaque: st.set_body(*elem_types) if is_packed: Gen.class_packed.add(class_name) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") stub_filename = source_sha1 + '.stub.ll' self._TryLoadClassMembersFromPyi(class_name, stub_filename, Gen) return @@ -1419,13 +1482,13 @@ class ImportHandle(BaseHandle): return source_sha1 = stub_filename.replace('.stub.ll', '') module_name = None - if hasattr(Gen, 'module_sha1_map'): - for mod_name, mod_sha1 in Gen.module_sha1_map.items(): + if hasattr(Gen, 'ModuleSha1Map'): + for mod_name, mod_sha1 in Gen.ModuleSha1Map.items(): if mod_sha1 == source_sha1 and '.' not in mod_name: module_name = mod_name break if module_name is None: - for mod_name, mod_sha1 in Gen.module_sha1_map.items(): + for mod_name, mod_sha1 in Gen.ModuleSha1Map.items(): if mod_sha1 == source_sha1: module_name = mod_name break @@ -1513,9 +1576,13 @@ class ImportHandle(BaseHandle): stub_ret = match.group(1).strip() stub_params = match.group(3).strip() self._stub_func_cache[stub_func_name] = (stub_ret, stub_params, '...' in stub_params, source_sha1) - except Exception: - pass - + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") + if func_name not in self._stub_func_cache: return None @@ -1622,8 +1689,8 @@ class ImportHandle(BaseHandle): target_sha1 = os.path.basename(val).replace('.pyi', '') break if not target_sha1: - module_sha1_map = getattr(Gen, 'module_sha1_map', {}) - target_sha1 = module_sha1_map.get(module_name) + ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) + target_sha1 = ModuleSha1Map.get(module_name) if target_sha1: target_stub = f"{target_sha1}.stub.ll" @@ -1648,21 +1715,25 @@ class ImportHandle(BaseHandle): elif stripped.startswith('declare '): for m in re.finditer(r'%\"?([a-f0-9]{16})\.', stripped): needed_sha1s.add(m.group(1)) - except Exception: - pass - - preload_files = [] + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") + + preLoad_files = [] for sha1 in needed_sha1s: dep_stub = f"{sha1}.stub.ll" if dep_stub in all_stub_files and dep_stub not in stub_files: - preload_files.append(dep_stub) + preLoad_files.append(dep_stub) - load_order = preload_files + stub_files + Load_order = preLoad_files + stub_files - for filename in load_order: + for filename in Load_order: stub_path = os.path.join(temp_dir, filename) source_sha1 = filename.replace('.stub.ll', '') - is_preload = filename in preload_files + is_preLoad = filename in preLoad_files try: with open(stub_path, 'r', encoding='utf-8') as f: content = f.read() @@ -1699,14 +1770,18 @@ class ImportHandle(BaseHandle): if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): try: st.set_body(*elem_types) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") continue if not stripped.startswith('declare '): continue - if is_preload: + if is_preLoad: continue func_name_match = stripped.split('@', 1) @@ -1736,10 +1811,18 @@ class ImportHandle(BaseHandle): if '.' in func_name: short_name = func_name.split('.', 1)[1] Gen.functions[short_name] = func - except Exception: - pass - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理导入失败: {_e}", "Exception") def _parse_llvm_declare(self, declare_line: str, Gen): """解析 LLVM declare 语句""" diff --git a/lib/core/Handles/HandlesMatch.py b/lib/core/Handles/HandlesMatch.py index 638feb8..f224008 100644 --- a/lib/core/Handles/HandlesMatch.py +++ b/lib/core/Handles/HandlesMatch.py @@ -1,333 +1,333 @@ -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 ast -import llvmlite.ir as ir - - -class MatchHandle(BaseHandle): - def _HandleMatchLlvm(self, Node): - Gen = self.Trans.LlvmGen - SubjectVal = self.HandleExprLlvm(Node.subject) - if not SubjectVal: - return - - IsRenumMatch = False - RenumName = None - SubjectPtr = None - if isinstance(Node.subject, ast.Name): - VarName = Node.subject.id - if VarName in self.Trans.SymbolTable: - TypeInfo = self.Trans.SymbolTable[VarName] - if getattr(TypeInfo, 'IsRenum', False): - IsRenumMatch = True - RenumName = TypeInfo.Name - SubjectPtr = Gen._load_var(VarName) - - if not IsRenumMatch: - for case in Node.cases: - if isinstance(case.pattern, ast.MatchClass): - cls_node = case.pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName and VariantName in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[VariantName] - if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None): - EnumName = SymInfo.EnumName - if EnumName in self.Trans.SymbolTable: - EnumInfo = self.Trans.SymbolTable[EnumName] - if getattr(EnumInfo, 'IsRenum', False): - IsRenumMatch = True - RenumName = EnumName - if SubjectPtr is None: - SubjectPtr = self.HandleExprLlvm(Node.subject) - break - - if IsRenumMatch and SubjectPtr: - self._HandleRenumMatchLlvm(Node, RenumName, SubjectPtr) - return - - if not isinstance(SubjectVal.type, ir.IntType): - try: - SubjectVal = Gen.builder.ptrtoint(SubjectVal, ir.IntType(64), name="match_subj") - SubjectVal = Gen.builder.trunc(SubjectVal, ir.IntType(32), name="match_subj_i32") - except Exception: # 回退:ptrtoint 失败时直接返回 - return - SwitchIntType = SubjectVal.type - DefaultBB = Gen.func.append_basic_block(name="match.default") - AfterBB = Gen.func.append_basic_block(name="match.end") - CaseBBs = [] - CaseValues = [] - HasDefault = False - HasNoBreak = [] - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchValue): - Val = self.HandleExprLlvm(pattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type != SwitchIntType: - if Val.type.width > SwitchIntType.width: - CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) - else: - CaseVal = ir.Constant(SwitchIntType, Val.constant) - else: - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(SwitchIntType, 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - elif isinstance(pattern, ast.MatchOr): - for j, SubPattern in enumerate(pattern.patterns): - if isinstance(SubPattern, ast.MatchValue): - Val = self.HandleExprLlvm(SubPattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type != SwitchIntType: - if Val.type.width > SwitchIntType.width: - CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) - else: - CaseVal = ir.Constant(SwitchIntType, Val.constant) - else: - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}_{j}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(SwitchIntType, 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}_{j}")) - elif isinstance(pattern, ast.MatchSingleton): - if pattern.value is None: - CaseValues.append(ir.Constant(SwitchIntType, 0)) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - HasDefault = True - CaseBBs.append(DefaultBB) - elif isinstance(pattern, ast.MatchSequence): - HasDefault = True - CaseBBs.append(DefaultBB) - def _HasNoBreak(stmts): - for stmt in stmts: - if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): - if isinstance(stmt.value.func, ast.Attribute): - if (isinstance(stmt.value.func.value, ast.Name) and - stmt.value.func.value.id == 'c' and - stmt.value.func.attr == 'NoBreak'): - return True - if getattr(stmt, 'body', None) and isinstance(stmt.body, list): - if _HasNoBreak(stmt.body): - return True - if getattr(stmt, 'orelse', None): - if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): - return True - return False - HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) - if not HasDefault: - CaseBBs.append(DefaultBB) - SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] - switch_instr = Gen.builder.switch(SubjectVal, DefaultBB) - for val, bb in SwitchCases: - switch_instr.add_case(val, bb) - CaseIdx = 0 - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchOr): - NumSubCases = len(pattern.patterns) - for j in range(NumSubCases): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, (ast.MatchValue, ast.MatchSingleton)): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchSequence): - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - if not HasDefault: - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - - def _HandleRenumMatchLlvm(self, Node, RenumName, SubjectPtr): - Gen = self.Trans.LlvmGen - if isinstance(SubjectPtr.type, ir.PointerType) and isinstance(SubjectPtr.type.pointee, ir.PointerType): - SubjectPtr = Gen._load(SubjectPtr, name="load_match_subj") - tag_ptr = Gen.builder.gep(SubjectPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="match_tag_ptr") - TagVal = Gen._load(tag_ptr, name="match_tag_val") - DefaultBB = Gen.func.append_basic_block(name="match.default") - AfterBB = Gen.func.append_basic_block(name="match.end") - CaseBBs = [] - CaseValues = [] - CaseBindings = [] - HasDefault = False - HasNoBreak = [] - for i, case in enumerate(Node.cases): - pattern = case.pattern - bindings = [] - if isinstance(pattern, ast.MatchClass): - cls_node = pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName: - TagValue = None - if VariantName in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[VariantName] - if getattr(SymInfo, 'IsEnumMember', False): - TagValue = SymInfo.value - if TagValue is not None: - CaseValues.append(ir.Constant(ir.IntType(32), TagValue)) - CaseBB = Gen.func.append_basic_block(name=f"match.case_{VariantName}") - CaseBBs.append(CaseBB) - NestedStructName = f"{RenumName}_{VariantName}" - if NestedStructName in Gen.structs: - members = Gen.class_members.get(NestedStructName, []) - payload_members = [(n, t) for n, t in members if n != '__tag'] - for j, sub_pat in enumerate(pattern.patterns): - if isinstance(sub_pat, ast.MatchAs) and sub_pat.name and j < len(payload_members): - bindings.append((sub_pat.name, payload_members[j][0], payload_members[j][1], j)) - CaseBindings.append(bindings) - else: - CaseValues.append(ir.Constant(ir.IntType(32), 0)) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchValue): - Val = self.HandleExprLlvm(pattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, ir.IntType(32), name=f"case_val_{i}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(ir.IntType(32), 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - HasDefault = True - CaseBBs.append(DefaultBB) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchSequence): - HasDefault = True - CaseBBs.append(DefaultBB) - CaseBindings.append([]) - def _HasNoBreak(stmts): - for stmt in stmts: - if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): - if isinstance(stmt.value.func, ast.Attribute): - if (isinstance(stmt.value.func.value, ast.Name) and - stmt.value.func.value.id == 'c' and - stmt.value.func.attr == 'NoBreak'): - return True - if getattr(stmt, 'body', None) and isinstance(stmt.body, list): - if _HasNoBreak(stmt.body): - return True - if getattr(stmt, 'orelse', None): - if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): - return True - return False - HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) - if not HasDefault: - CaseBBs.append(DefaultBB) - SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] - switch_instr = Gen.builder.switch(TagVal, DefaultBB) - for val, bb in SwitchCases: - switch_instr.add_case(val, bb) - CaseIdx = 0 - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchClass): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - bindings = CaseBindings[CaseIdx] if CaseIdx < len(CaseBindings) else [] - cls_node = pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName: - NestedStructName = f"{RenumName}_{VariantName}" - if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] - NestedStructPtrType = ir.PointerType(NestedStructType) - variant_ptr = Gen.builder.bitcast(SubjectPtr, NestedStructPtrType, name=f"match_cast_{VariantName}") - for bind_name, member_name, member_type, member_idx in bindings: - elem_ptr = Gen.builder.gep(variant_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), member_idx + 1)], name=f"match_{bind_name}") - Gen.variables[bind_name] = elem_ptr - self.HandleBodyLlvm(case.body) - for bind_name, _, _, _ in bindings: - if bind_name in Gen.variables: - del Gen.variables[bind_name] - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchValue): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchSequence): - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - if not HasDefault: - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(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 ast +import llvmlite.ir as ir + + +class MatchHandle(BaseHandle): + def _HandleMatchLlvm(self, Node): + Gen = self.Trans.LlvmGen + SubjectVal = self.HandleExprLlvm(Node.subject) + if not SubjectVal: + return + + IsRenumMatch = False + RenumName = None + SubjectPtr = None + if isinstance(Node.subject, ast.Name): + VarName = Node.subject.id + if VarName in self.Trans.SymbolTable: + TypeInfo = self.Trans.SymbolTable[VarName] + if getattr(TypeInfo, 'IsRenum', False): + IsRenumMatch = True + RenumName = TypeInfo.Name + SubjectPtr = Gen._loadVar(VarName) + + if not IsRenumMatch: + for case in Node.cases: + if isinstance(case.pattern, ast.MatchClass): + cls_node = case.pattern.cls + VariantName = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName and VariantName in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[VariantName] + if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None): + EnumName = SymInfo.EnumName + if EnumName in self.Trans.SymbolTable: + EnumInfo = self.Trans.SymbolTable[EnumName] + if getattr(EnumInfo, 'IsRenum', False): + IsRenumMatch = True + RenumName = EnumName + if SubjectPtr is None: + SubjectPtr = self.HandleExprLlvm(Node.subject) + break + + if IsRenumMatch and SubjectPtr: + self._HandleRenumMatchLlvm(Node, RenumName, SubjectPtr) + return + + if not isinstance(SubjectVal.type, ir.IntType): + try: + SubjectVal = Gen.builder.ptrtoint(SubjectVal, ir.IntType(64), name="match_subj") + SubjectVal = Gen.builder.trunc(SubjectVal, ir.IntType(32), name="match_subj_i32") + except Exception: # 回退:ptrtoint 失败时直接返回 + return + SwitchIntType = SubjectVal.type + DefaultBB = Gen.func.append_basic_block(name="match.default") + AfterBB = Gen.func.append_basic_block(name="match.end") + CaseBBs = [] + CaseValues = [] + HasDefault = False + HasNoBreak = [] + for i, case in enumerate(Node.cases): + pattern = case.pattern + if isinstance(pattern, ast.MatchValue): + Val = self.HandleExprLlvm(pattern.value) + if Val: + if isinstance(Val.type, ir.IntType): + if Val.type != SwitchIntType: + if Val.type.width > SwitchIntType.width: + CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) + else: + CaseVal = ir.Constant(SwitchIntType, Val.constant) + else: + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(SwitchIntType, 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + elif isinstance(pattern, ast.MatchOr): + for j, SubPattern in enumerate(pattern.patterns): + if isinstance(SubPattern, ast.MatchValue): + Val = self.HandleExprLlvm(SubPattern.value) + if Val: + if isinstance(Val.type, ir.IntType): + if Val.type != SwitchIntType: + if Val.type.width > SwitchIntType.width: + CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) + else: + CaseVal = ir.Constant(SwitchIntType, Val.constant) + else: + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}_{j}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(SwitchIntType, 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}_{j}")) + elif isinstance(pattern, ast.MatchSingleton): + if pattern.value is None: + CaseValues.append(ir.Constant(SwitchIntType, 0)) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + HasDefault = True + CaseBBs.append(DefaultBB) + elif isinstance(pattern, ast.MatchSequence): + HasDefault = True + CaseBBs.append(DefaultBB) + def _HasNoBreak(stmts): + for stmt in stmts: + if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): + if isinstance(stmt.value.func, ast.Attribute): + if (isinstance(stmt.value.func.value, ast.Name) and + stmt.value.func.value.id == 'c' and + stmt.value.func.attr == 'NoBreak'): + return True + if getattr(stmt, 'body', None) and isinstance(stmt.body, list): + if _HasNoBreak(stmt.body): + return True + if getattr(stmt, 'orelse', None): + if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): + return True + return False + HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) + if not HasDefault: + CaseBBs.append(DefaultBB) + SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] + switch_instr = Gen.builder.switch(SubjectVal, DefaultBB) + for val, bb in SwitchCases: + switch_instr.add_case(val, bb) + CaseIdx = 0 + for i, case in enumerate(Node.cases): + pattern = case.pattern + if isinstance(pattern, ast.MatchOr): + NumSubCases = len(pattern.patterns) + for j in range(NumSubCases): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, (ast.MatchValue, ast.MatchSingleton)): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchSequence): + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + if not HasDefault: + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleRenumMatchLlvm(self, Node, RenumName, SubjectPtr): + Gen = self.Trans.LlvmGen + if isinstance(SubjectPtr.type, ir.PointerType) and isinstance(SubjectPtr.type.pointee, ir.PointerType): + SubjectPtr = Gen._load(SubjectPtr, name="Load_match_subj") + tag_ptr = Gen.builder.gep(SubjectPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="match_tag_ptr") + TagVal = Gen._load(tag_ptr, name="match_tag_val") + DefaultBB = Gen.func.append_basic_block(name="match.default") + AfterBB = Gen.func.append_basic_block(name="match.end") + CaseBBs = [] + CaseValues = [] + CaseBindings = [] + HasDefault = False + HasNoBreak = [] + for i, case in enumerate(Node.cases): + pattern = case.pattern + bindings = [] + if isinstance(pattern, ast.MatchClass): + cls_node = pattern.cls + VariantName = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName: + TagValue = None + if VariantName in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[VariantName] + if getattr(SymInfo, 'IsEnumMember', False): + TagValue = SymInfo.value + if TagValue is not None: + CaseValues.append(ir.Constant(ir.IntType(32), TagValue)) + CaseBB = Gen.func.append_basic_block(name=f"match.case_{VariantName}") + CaseBBs.append(CaseBB) + NestedStructName = f"{RenumName}_{VariantName}" + if NestedStructName in Gen.structs: + members = Gen.class_members.get(NestedStructName, []) + payLoad_members = [(n, t) for n, t in members if n != '__tag'] + for j, sub_pat in enumerate(pattern.patterns): + if isinstance(sub_pat, ast.MatchAs) and sub_pat.name and j < len(payLoad_members): + bindings.append((sub_pat.name, payLoad_members[j][0], payLoad_members[j][1], j)) + CaseBindings.append(bindings) + else: + CaseValues.append(ir.Constant(ir.IntType(32), 0)) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchValue): + Val = self.HandleExprLlvm(pattern.value) + if Val: + if isinstance(Val.type, ir.IntType): + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, ir.IntType(32), name=f"case_val_{i}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(ir.IntType(32), 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + HasDefault = True + CaseBBs.append(DefaultBB) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchSequence): + HasDefault = True + CaseBBs.append(DefaultBB) + CaseBindings.append([]) + def _HasNoBreak(stmts): + for stmt in stmts: + if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): + if isinstance(stmt.value.func, ast.Attribute): + if (isinstance(stmt.value.func.value, ast.Name) and + stmt.value.func.value.id == 'c' and + stmt.value.func.attr == 'NoBreak'): + return True + if getattr(stmt, 'body', None) and isinstance(stmt.body, list): + if _HasNoBreak(stmt.body): + return True + if getattr(stmt, 'orelse', None): + if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): + return True + return False + HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) + if not HasDefault: + CaseBBs.append(DefaultBB) + SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] + switch_instr = Gen.builder.switch(TagVal, DefaultBB) + for val, bb in SwitchCases: + switch_instr.add_case(val, bb) + CaseIdx = 0 + for i, case in enumerate(Node.cases): + pattern = case.pattern + if isinstance(pattern, ast.MatchClass): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + bindings = CaseBindings[CaseIdx] if CaseIdx < len(CaseBindings) else [] + cls_node = pattern.cls + VariantName = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName: + NestedStructName = f"{RenumName}_{VariantName}" + if NestedStructName in Gen.structs: + NestedStructType = Gen.structs[NestedStructName] + NestedStructPtrType = ir.PointerType(NestedStructType) + variant_ptr = Gen.builder.bitcast(SubjectPtr, NestedStructPtrType, name=f"match_cast_{VariantName}") + for bind_name, member_name, member_type, member_idx in bindings: + elem_ptr = Gen.builder.gep(variant_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), member_idx + 1)], name=f"match_{bind_name}") + Gen.variables[bind_name] = elem_ptr + self.HandleBodyLlvm(case.body) + for bind_name, _, _, _ in bindings: + if bind_name in Gen.variables: + del Gen.variables[bind_name] + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchValue): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchSequence): + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + if not HasDefault: + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) diff --git a/lib/core/Handles/HandlesRaise.py b/lib/core/Handles/HandlesRaise.py index c1ecef3..b48ad65 100644 --- a/lib/core/Handles/HandlesRaise.py +++ b/lib/core/Handles/HandlesRaise.py @@ -1,135 +1,135 @@ -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, EXCEPTION_CODE_MAP -import ast -import llvmlite.ir as ir - - -class RaiseHandle(BaseHandle): - def _get_exception_code(self, ExcName): - if ExcName in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[ExcName] - if ExcName in self.Trans.exception_registry: - return self.Trans.exception_registry[ExcName] - return 1 - - def _HandleRaiseLlvm(self, Node): - Gen = self.Trans.LlvmGen - exc_val = ir.Constant(ir.IntType(32), 1) - exc_msg = None - IsStopIteration = False - if Node.exc: - if isinstance(Node.exc, ast.Constant) and isinstance(Node.exc.value, int): - exc_val = ir.Constant(ir.IntType(32), Node.exc.value) - elif isinstance(Node.exc, ast.Name): - ExcName = Node.exc.id - if ExcName == 'StopIteration': - IsStopIteration = True - exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) - elif isinstance(Node.exc, ast.Call) and isinstance(Node.exc.func, ast.Name): - ExcName = Node.exc.func.id - if ExcName == 'StopIteration': - IsStopIteration = True - exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) - if Node.exc.args: - first_arg = Node.exc.args[0] - if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - exc_msg = self.HandleExprLlvm(first_arg) - elif isinstance(first_arg, (ast.Name, ast.Call, ast.Attribute)): - arg_val = self.HandleExprLlvm(first_arg) - if arg_val: - if isinstance(arg_val.type, ir.PointerType): - if self._is_char_pointer(arg_val): - exc_msg = arg_val - else: - try: - exc_msg = Gen.builder.bitcast(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_cast") - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - else: - try: - exc_msg = Gen.builder.inttoptr(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_ptr") - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - else: - val = self.HandleExprLlvm(Node.exc) - if val: - if isinstance(val.type, ir.IntType): - if val.type.width != 32: - try: - val = Gen.builder.trunc(val, ir.IntType(32), name="exc_trunc") - except Exception: # 回退:trunc 失败时设默认值 1 - val = ir.Constant(ir.IntType(32), 1) - exc_val = val - else: - try: - val = Gen.builder.ptrtoint(val, ir.IntType(32), name="exc_ptr2int") - exc_val = val - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - if IsStopIteration: - if Gen._stop_iter_flag_param is not None: - Gen.builder.store(ir.Constant(ir.IntType(1), 1), Gen._stop_iter_flag_param) - if Gen.func and Gen.func.type.pointee.return_type != ir.VoidType(): - ret_type = Gen.func.type.pointee.return_type - Gen.builder.ret(ir.Constant(ret_type, 0)) - else: - Gen.builder.ret_void() - return - if Gen.eh_except_block_stack: - ExceptBB, EndBB, exception_code, eh_message = Gen.eh_except_block_stack[-1] - Gen._store(exc_val, exception_code) - if exc_msg: - Gen._store(exc_msg, eh_message) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen._store(null_ptr, eh_message) - if Gen.func and ExceptBB and ExceptBB.function is Gen.func: - Gen.builder.branch(ExceptBB) - else: - eh_msg_arg = None - eh_code_arg = None - if Gen.func: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_arg = arg - if eh_msg_arg is not None: - if exc_msg: - Gen.builder.store(exc_msg, eh_msg_arg) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen.builder.store(null_ptr, eh_msg_arg) - if eh_code_arg is not None: - Gen.builder.store(exc_val, eh_code_arg) - if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: - Gen.builder.ret_void() - else: - eh_msg_arg = None - eh_code_arg = None - if Gen.func: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_arg = arg - if eh_msg_arg is not None: - if exc_msg: - Gen.builder.store(exc_msg, eh_msg_arg) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen.builder.store(null_ptr, eh_msg_arg) - if eh_code_arg is not None: - Gen.builder.store(exc_val, eh_code_arg) - if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: +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, EXCEPTION_CODE_MAP +import ast +import llvmlite.ir as ir + + +class RaiseHandle(BaseHandle): + def _get_exception_code(self, ExcName): + if ExcName in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[ExcName] + if ExcName in self.Trans.exception_registry: + return self.Trans.exception_registry[ExcName] + return 1 + + def _HandleRaiseLlvm(self, Node): + Gen = self.Trans.LlvmGen + exc_val = ir.Constant(ir.IntType(32), 1) + exc_msg = None + IsStopIteration = False + if Node.exc: + if isinstance(Node.exc, ast.Constant) and isinstance(Node.exc.value, int): + exc_val = ir.Constant(ir.IntType(32), Node.exc.value) + elif isinstance(Node.exc, ast.Name): + ExcName = Node.exc.id + if ExcName == 'StopIteration': + IsStopIteration = True + exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) + elif isinstance(Node.exc, ast.Call) and isinstance(Node.exc.func, ast.Name): + ExcName = Node.exc.func.id + if ExcName == 'StopIteration': + IsStopIteration = True + exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) + if Node.exc.args: + first_arg = Node.exc.args[0] + if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): + exc_msg = self.HandleExprLlvm(first_arg) + elif isinstance(first_arg, (ast.Name, ast.Call, ast.Attribute)): + arg_val = self.HandleExprLlvm(first_arg) + if arg_val: + if isinstance(arg_val.type, ir.PointerType): + if self._is_char_pointer(arg_val): + exc_msg = arg_val + else: + try: + exc_msg = Gen.builder.bitcast(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_cast") + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + else: + try: + exc_msg = Gen.builder.inttoptr(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_ptr") + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + else: + val = self.HandleExprLlvm(Node.exc) + if val: + if isinstance(val.type, ir.IntType): + if val.type.width != 32: + try: + val = Gen.builder.trunc(val, ir.IntType(32), name="exc_trunc") + except Exception: # 回退:trunc 失败时设默认值 1 + val = ir.Constant(ir.IntType(32), 1) + exc_val = val + else: + try: + val = Gen.builder.ptrtoint(val, ir.IntType(32), name="exc_ptr2int") + exc_val = val + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + if IsStopIteration: + if Gen._stop_iter_flag_param is not None: + Gen.builder.store(ir.Constant(ir.IntType(1), 1), Gen._stop_iter_flag_param) + if Gen.func and Gen.func.type.pointee.return_type != ir.VoidType(): + ret_type = Gen.func.type.pointee.return_type + Gen.builder.ret(ir.Constant(ret_type, 0)) + else: + Gen.builder.ret_void() + return + if Gen.eh_except_block_stack: + ExceptBB, EndBB, exception_code, eh_message = Gen.eh_except_block_stack[-1] + Gen._store(exc_val, exception_code) + if exc_msg: + Gen._store(exc_msg, eh_message) + else: + null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen._store(null_ptr, eh_message) + if Gen.func and ExceptBB and ExceptBB.function is Gen.func: + Gen.builder.branch(ExceptBB) + else: + eh_msg_arg = None + eh_code_arg = None + if Gen.func: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_arg = arg + if eh_msg_arg is not None: + if exc_msg: + Gen.builder.store(exc_msg, eh_msg_arg) + else: + null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen.builder.store(null_ptr, eh_msg_arg) + if eh_code_arg is not None: + Gen.builder.store(exc_val, eh_code_arg) + if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: + Gen.builder.ret_void() + else: + eh_msg_arg = None + eh_code_arg = None + if Gen.func: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_arg = arg + if eh_msg_arg is not None: + if exc_msg: + Gen.builder.store(exc_msg, eh_msg_arg) + else: + null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen.builder.store(null_ptr, eh_msg_arg) + if eh_code_arg is not None: + Gen.builder.store(exc_val, eh_code_arg) + if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: Gen.builder.ret_void() \ No newline at end of file diff --git a/lib/core/Handles/HandlesSpecialCall.py b/lib/core/Handles/HandlesSpecialCall.py index f2d57be..29520a1 100644 --- a/lib/core/Handles/HandlesSpecialCall.py +++ b/lib/core/Handles/HandlesSpecialCall.py @@ -1,354 +1,358 @@ -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 ast -import llvmlite.ir as ir - - -class CSpecialCallHandle(BaseHandle): - def _HandleCIfLlvm(self, Node): - Gen = self.Trans.LlvmGen - if Node.args: - ArgVal = self.HandleExprLlvm(Node.args[0]) - if ArgVal: - if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType): - return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0) - if isinstance(ArgVal.type, ir.IntType): - return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond") - if isinstance(ArgVal.type, ir.PointerType): - return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond") - return ir.Constant(ir.IntType(1), 0) - def _HandleCAddrLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Node.args: - return ir.Constant(ir.IntType(8).as_pointer(), None) - Arg = Node.args[0] - if isinstance(Arg, ast.Call): - ClassName = None - if isinstance(Arg.func, ast.Name): - ClassName = Arg.func.id - elif isinstance(Arg.func, ast.Attribute): - ClassName = Arg.func.attr - if ClassName and ClassName in Gen.structs: - StructType = Gen.structs[ClassName] - if isinstance(StructType, ir.PointerType): - StructType = StructType.pointee - ObjPtr = Gen._alloca_entry(StructType, name=f"{ClassName}_obj") - Gen.builder.store(ir.Constant(StructType, None), ObjPtr) - ConstructorName = f"{ClassName}.__init__" - if ConstructorName in Gen.functions: - func = Gen.functions[ConstructorName] - InitArgs = [ObjPtr] - for carg in Arg.args: - ArgVal = self.HandleExprLlvm(carg) - if ArgVal: - InitArgs.append(ArgVal) - for kw in Arg.keywords: - ArgVal = self.HandleExprLlvm(kw.value) - if ArgVal: - InitArgs.append(ArgVal) - if hasattr(self.Trans.ExprCallHandle, '_append_eh_msg_out_arg'): - self.Trans.ExprCallHandle._append_eh_msg_out_arg(InitArgs, func, Gen) - adjusted = Gen._adjust_args(InitArgs, func) - Gen.builder.call(func, adjusted, name=f"{ClassName}_construct") - return Gen.builder.bitcast(ObjPtr, ir.IntType(8).as_pointer(), name=f"{ClassName}_as_i8ptr") - if isinstance(Arg, ast.Subscript): - SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Arg) - if SubPtr and isinstance(SubPtr.type, ir.PointerType): - return Gen.builder.bitcast(SubPtr, ir.IntType(8).as_pointer(), name="addr_subscript_as_i8ptr") - if isinstance(Arg, ast.Attribute): - AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Arg) - if AttrPtr and isinstance(AttrPtr.type, ir.PointerType): - return Gen.builder.bitcast(AttrPtr, ir.IntType(8).as_pointer(), name="addr_attr_as_i8ptr") - if isinstance(Arg, ast.Name): - VarName = Arg.id - if VarName in Gen.functions: - func = Gen.functions[VarName] - return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name="addr_func_as_i8ptr") - if VarName in Gen.variables and Gen.variables[VarName] is not None: - var_ptr = Gen.variables[VarName] - if isinstance(var_ptr.type, ir.PointerType): - # For pointer-to-pointer allocas (var_ptr is T**): - # - If T is a named struct (@t.Object class), the variable semantically - # IS the struct, so c.Addr should return the struct pointer value. - # - If T is a primitive pointer type (e.g., i8*), the variable semantically - # holds a pointer, so c.Addr should return &var (alloca address). - if isinstance(var_ptr.type.pointee, ir.PointerType): - pointee = var_ptr.type.pointee.pointee - if isinstance(pointee, ir.IdentifiedStructType): - # @t.Object class variable — return loaded struct pointer - ArgVal = self.HandleExprLlvm(Arg) - if ArgVal and isinstance(ArgVal.type, ir.PointerType): - return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") - # Pointer-type variable — return alloca address (&var) - return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") - return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") - ArgVal = self.HandleExprLlvm(Arg) - if ArgVal: - if isinstance(ArgVal.type, ir.IntType): - alloca = Gen._alloca(ArgVal.type, name="addr_tmp") - Gen._store(ArgVal, alloca) - return Gen.builder.bitcast(alloca, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") - elif isinstance(ArgVal.type, ir.PointerType): - return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_bitcast") - return ir.Constant(ir.IntType(8).as_pointer(), None) - - def _HandleCSetLlvm(self, Node): - Gen = self.Trans.LlvmGen - if len(Node.args) >= 2: - target_arg = Node.args[0] - value_arg = Node.args[1] - target_ptr = None - if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute): - if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c': - if target_arg.func.attr == 'Deref' and target_arg.args: - deref_arg = target_arg.args[0] - if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None: - target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr") - else: - inner_value = self.HandleExprLlvm(deref_arg) - if inner_value: - if isinstance(inner_value.type, ir.PointerType): - if isinstance(inner_value.type.pointee, ir.PointerType): - inner_value = Gen._load(inner_value, name="cast_deref") - target_ptr = inner_value - elif target_arg.func.attr == 'Addr' and target_arg.args: - target_ptr = self.HandleExprLlvm(target_arg) - elif isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 't': - type_attr = target_arg.func.attr - resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr) - if target_arg.args and resolved_cname is not None: - inner_val = self.HandleExprLlvm(target_arg.args[0]) - if inner_val and isinstance(inner_val.type, ir.PointerType): - target_llvm_type = Gen._basic_type_to_llvm(resolved_cname) - if target_llvm_type: - target_ptr = Gen.builder.bitcast(inner_val, ir.PointerType(target_llvm_type), name="tcast_ptr") - if not target_ptr: - if isinstance(target_arg, ast.Subscript): - target_ptr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(target_arg) - else: - target_ptr = self.HandleExprLlvm(target_arg) - Val = self.HandleExprLlvm(value_arg) - if target_ptr and Val: - if isinstance(target_ptr.type, ir.PointerType): - ValToStore = Val - pointee = target_ptr.type.pointee - if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8: - if isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8: - ValToStore = Val - elif isinstance(Val.type, ir.IntType): - ValToStore = Gen.builder.inttoptr(Val, pointee, name="int_to_ptr_set") - elif isinstance(pointee, ir.IntType): - if isinstance(Val.type, ir.ArrayType) and isinstance(Val.type.element, ir.IntType) and Val.type.element.width == 8: - zero = ir.Constant(ir.IntType(32), 0) - value_ptr = Gen.builder.gep(Val, [zero, zero], name="value_ptr") - ValToStore = Gen._load(value_ptr, name="load_value") - elif isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8: - ValToStore = Gen._load(Val, name="load_char_value") - if isinstance(ValToStore.type, ir.IntType) and isinstance(pointee, ir.IntType): - if ValToStore.type.width < pointee.width: - ValToStore = Gen.builder.zext(ValToStore, pointee, name="zext_set") - elif ValToStore.type.width > pointee.width: - ValToStore = Gen.builder.trunc(ValToStore, pointee, name="trunc_set") - elif Val.type != pointee: - if isinstance(pointee, ir.PointerType) and isinstance(Val.type, ir.PointerType): - ValToStore = Gen.builder.bitcast(Val, pointee, name="bitcast_set") - Gen._store(ValToStore, target_ptr) - return ir.Constant(ir.IntType(32), 1) - - def _HandleCLoadLlvm(self, Node): - Gen = self.Trans.LlvmGen - if len(Node.args) < 2: - return ir.Constant(ir.IntType(32), 0) - src_val = self.HandleExprLlvm(Node.args[0]) - dst_val = self.HandleExprLlvm(Node.args[1]) - if not src_val or not dst_val: - return ir.Constant(ir.IntType(32), 0) - if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType): - return ir.Constant(ir.IntType(32), 0) - loaded = Gen._load(src_val, name="cload_src") - if loaded is None: - return ir.Constant(ir.IntType(32), 0) - pointee = dst_val.type.pointee - val_to_store = loaded - if isinstance(pointee, ir.IntType) and isinstance(loaded.type, ir.IntType): - if loaded.type.width < pointee.width: - val_to_store = Gen.builder.zext(loaded, pointee, name="cload_zext") - elif loaded.type.width > pointee.width: - val_to_store = Gen.builder.trunc(loaded, pointee, name="cload_trunc") - elif isinstance(pointee, ir.PointerType) and isinstance(loaded.type, ir.PointerType): - val_to_store = Gen.builder.bitcast(loaded, pointee, name="cload_bitcast") - elif loaded.type != pointee: - target_ptr = Gen.builder.bitcast(src_val, ir.PointerType(pointee), name="cload_cast") - loaded = Gen._load(target_ptr, name="cload_casted") - if loaded is None: - return ir.Constant(ir.IntType(32), 0) - val_to_store = loaded - Gen._store(val_to_store, dst_val) - return ir.Constant(ir.IntType(32), 1) - - def _HandleCDerefLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Node.args: - return ir.Constant(ir.IntType(64), 0) - arg_val = self.HandleExprLlvm(Node.args[0]) - if arg_val is None: - return ir.Constant(ir.IntType(32), 0) - if isinstance(arg_val.type, ir.PointerType): - loaded = Gen._load(arg_val, name="deref") - if loaded is not None: - return loaded - return arg_val - - def _HandleCPtrToIntLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Node.args: - return ir.Constant(ir.IntType(64), 0) - arg_val = self.HandleExprLlvm(Node.args[0]) - if arg_val is None: - return ir.Constant(ir.IntType(64), 0) - if isinstance(arg_val.type, ir.PointerType): - return Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptrtoint_result") - if isinstance(arg_val.type, ir.IntType): - if arg_val.type.width < 64: - return Gen.builder.zext(arg_val, ir.IntType(64), name="zext_ptrtoint") - elif arg_val.type.width > 64: - return Gen.builder.trunc(arg_val, ir.IntType(64), name="trunc_ptrtoint") - return arg_val - return ir.Constant(ir.IntType(64), 0) - - -class TSpecialCallHandle(BaseHandle): - - @staticmethod - def _ResolveTAttrToCName(attr: str) -> str: - from lib.includes.t import CTypeRegistry - ctype_cls = CTypeRegistry.GetClassByName(attr) - if ctype_cls is not None: - try: - inst = ctype_cls() - cname = getattr(inst, 'CName', '') - if cname: - return cname - except Exception: - pass - return None - - def _HandleTSpecialCallLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Node.args: - return None - attr = Node.func.attr - - if attr == 'CType': - return self._HandleCTypeLlvm(Node) - - target_type = self._ResolveTAttrToCName(attr) - if target_type is not None: - is_ptr_cast = False - if len(Node.args) >= 2: - second_arg = Node.args[1] - if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and second_arg.value.id == 't' and second_arg.attr == 'CPtr': - is_ptr_cast = True - elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr': - is_ptr_cast = True - if is_ptr_cast: - return self._HandleTPtrCastLlvm(Node, attr) - if target_type == 'void': - target_type = 'void *' - return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type) - return None - - def _HandleCTypeLlvm(self, Node): - Gen = self.Trans.LlvmGen - arg_val = self.HandleExprLlvm(Node.args[0]) - if not arg_val: - return None - target_type_str = 'unsigned long long' - if len(Node.args) >= 2: - type_parts = [] - ptr_count = 0 - for i in range(1, len(Node.args)): - type_arg = Node.args[i] - if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't': - type_attr = type_arg.attr - _PREFIX_MAP = { - 'CUnsigned': 'unsigned', 'CSigned': 'signed', - 'CConst': 'const', 'CVolatile': 'volatile', - } - if type_attr in _PREFIX_MAP: - type_parts.append(_PREFIX_MAP[type_attr]) - elif type_attr in ('CPtr', 'CArrayPtr'): - ptr_count += 1 - else: - resolved = self._ResolveTAttrToCName(type_attr) - if resolved is not None: - type_parts.append(resolved) - if type_parts: - target_type_str = ' '.join(type_parts) - if ptr_count > 0: - target_type_str += ' ' + '*' * ptr_count - if isinstance(arg_val.type, ir.PointerType): - int_val = Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptr_to_int") - return int_val - return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str) - - def _HandleTPtrCastLlvm(self, Node, attr): - Gen = self.Trans.LlvmGen - from lib.includes.t import CTypeRegistry - if attr in ('CChar', 'CUnsignedChar'): - first_arg = Node.args[0] - if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and first_arg.func.value.id == 't' and first_arg.func.attr == 'CInt' and first_arg.args: - inner_val = self.HandleExprLlvm(first_arg.args[0]) - if isinstance(inner_val.type, ir.PointerType): - return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint") - expr_val = self.HandleExprLlvm(Node.args[0]) - if isinstance(expr_val.type, ir.IntType) and expr_val.type.width == 8: - var = Gen._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"c{attr.lower()}_ptr") - zero = ir.Constant(ir.IntType(32), 0) - char_ptr = Gen.builder.gep(var, [zero, zero], name="char_ptr") - Gen._store(expr_val, char_ptr) - null_char = ir.Constant(ir.IntType(8), 0) - null_ptr = Gen.builder.gep(var, [zero, ir.Constant(ir.IntType(32), 1)], name="null_ptr") - Gen._store(null_char, null_ptr) - return char_ptr - elif isinstance(expr_val.type, ir.PointerType): - if isinstance(expr_val.type.pointee, ir.PointerType): - loaded_ptr = Gen._load(expr_val, name="load_ptr") - if isinstance(loaded_ptr.type, ir.PointerType) and isinstance(loaded_ptr.type.pointee, ir.IntType) and loaded_ptr.type.pointee.width == 8: - return loaded_ptr - if isinstance(expr_val.type.pointee, ir.IntType) and expr_val.type.pointee.width == 8: - return expr_val - return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(8)), name="cast_to_char_ptr") - elif isinstance(expr_val.type, ir.IntType): - if expr_val.type.width == 32: - expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") - return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(8)), name=f"inttoptr_c{attr.lower()}") - return Gen.emit_constant(0, 'int') - elif attr == 'CVoid': - return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], 'void *') - elif attr == 'CInt': - expr_val = self.HandleExprLlvm(Node.args[0]) - if expr_val: - if isinstance(expr_val.type, ir.IntType): - if expr_val.type.width < 64: - expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") - return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr") - return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr") - else: - ctype_cls = CTypeRegistry.GetClassByName(attr) - if ctype_cls is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - target_type = Gen._type_str_to_llvm(llvm_str) - if target_type and isinstance(target_type, (ir.IntType, ir.FloatType, ir.DoubleType)): - target_ptr_type = ir.PointerType(target_type) - expr_val = self.HandleExprLlvm(Node.args[0]) - if expr_val: - if isinstance(expr_val.type, ir.IntType): - if expr_val.type.width < 64: - expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") - return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr") - return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr") - return None +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 ast +import llvmlite.ir as ir + + +class CSpecialCallHandle(BaseHandle): + def _HandleCIfLlvm(self, Node): + Gen = self.Trans.LlvmGen + if Node.args: + ArgVal = self.HandleExprLlvm(Node.args[0]) + if ArgVal: + if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType): + return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0) + if isinstance(ArgVal.type, ir.IntType): + return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond") + if isinstance(ArgVal.type, ir.PointerType): + return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond") + return ir.Constant(ir.IntType(1), 0) + def _HandleCAddrLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not Node.args: + return ir.Constant(ir.IntType(8).as_pointer(), None) + Arg = Node.args[0] + if isinstance(Arg, ast.Call): + ClassName = None + if isinstance(Arg.func, ast.Name): + ClassName = Arg.func.id + elif isinstance(Arg.func, ast.Attribute): + ClassName = Arg.func.attr + if ClassName and ClassName in Gen.structs: + StructType = Gen.structs[ClassName] + if isinstance(StructType, ir.PointerType): + StructType = StructType.pointee + ObjPtr = Gen._allocaEntry(StructType, name=f"{ClassName}_obj") + Gen.builder.store(ir.Constant(StructType, None), ObjPtr) + ConstructorName = f"{ClassName}.__init__" + if ConstructorName in Gen.functions: + func = Gen.functions[ConstructorName] + InitArgs = [ObjPtr] + for carg in Arg.args: + ArgVal = self.HandleExprLlvm(carg) + if ArgVal: + InitArgs.append(ArgVal) + for kw in Arg.keywords: + ArgVal = self.HandleExprLlvm(kw.value) + if ArgVal: + InitArgs.append(ArgVal) + if hasattr(self.Trans.ExprCallHandle, '_append_eh_msg_out_arg'): + self.Trans.ExprCallHandle._append_eh_msg_out_arg(InitArgs, func, Gen) + adjusted = Gen._adjust_args(InitArgs, func) + Gen.builder.call(func, adjusted, name=f"{ClassName}_construct") + return Gen.builder.bitcast(ObjPtr, ir.IntType(8).as_pointer(), name=f"{ClassName}_as_i8ptr") + if isinstance(Arg, ast.Subscript): + SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Arg) + if SubPtr and isinstance(SubPtr.type, ir.PointerType): + return Gen.builder.bitcast(SubPtr, ir.IntType(8).as_pointer(), name="addr_subscript_as_i8ptr") + if isinstance(Arg, ast.Attribute): + AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Arg) + if AttrPtr and isinstance(AttrPtr.type, ir.PointerType): + return Gen.builder.bitcast(AttrPtr, ir.IntType(8).as_pointer(), name="addr_attr_as_i8ptr") + if isinstance(Arg, ast.Name): + VarName = Arg.id + if VarName in Gen.functions: + func = Gen.functions[VarName] + return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name="addr_func_as_i8ptr") + if VarName in Gen.variables and Gen.variables[VarName] is not None: + var_ptr = Gen.variables[VarName] + if isinstance(var_ptr.type, ir.PointerType): + # For pointer-to-pointer allocas (var_ptr is T**): + # - If T is a named struct (@t.Object class), the variable semantically + # IS the struct, so c.Addr should return the struct pointer value. + # - If T is a primitive pointer type (e.g., i8*), the variable semantically + # holds a pointer, so c.Addr should return &var (alloca address). + if isinstance(var_ptr.type.pointee, ir.PointerType): + pointee = var_ptr.type.pointee.pointee + if isinstance(pointee, ir.IdentifiedStructType): + # @t.Object class variable — return Loaded struct pointer + ArgVal = self.HandleExprLlvm(Arg) + if ArgVal and isinstance(ArgVal.type, ir.PointerType): + return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") + # Pointer-type variable — return alloca address (&var) + return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") + return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") + ArgVal = self.HandleExprLlvm(Arg) + if ArgVal: + if isinstance(ArgVal.type, ir.IntType): + alloca = Gen._alloca(ArgVal.type, name="addr_tmp") + Gen._store(ArgVal, alloca) + return Gen.builder.bitcast(alloca, ir.IntType(8).as_pointer(), name="addr_as_i8ptr") + elif isinstance(ArgVal.type, ir.PointerType): + return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_bitcast") + return ir.Constant(ir.IntType(8).as_pointer(), None) + + def _HandleCSetLlvm(self, Node): + Gen = self.Trans.LlvmGen + if len(Node.args) >= 2: + target_arg = Node.args[0] + value_arg = Node.args[1] + target_ptr = None + if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute): + if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c': + if target_arg.func.attr == 'Deref' and target_arg.args: + deref_arg = target_arg.args[0] + if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None: + target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr") + else: + inner_value = self.HandleExprLlvm(deref_arg) + if inner_value: + if isinstance(inner_value.type, ir.PointerType): + if isinstance(inner_value.type.pointee, ir.PointerType): + inner_value = Gen._load(inner_value, name="cast_deref") + target_ptr = inner_value + elif target_arg.func.attr == 'Addr' and target_arg.args: + target_ptr = self.HandleExprLlvm(target_arg) + elif isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 't': + type_attr = target_arg.func.attr + resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr) + if target_arg.args and resolved_cname is not None: + inner_val = self.HandleExprLlvm(target_arg.args[0]) + if inner_val and isinstance(inner_val.type, ir.PointerType): + target_llvm_type = Gen._basic_type_to_llvm(resolved_cname) + if target_llvm_type: + target_ptr = Gen.builder.bitcast(inner_val, ir.PointerType(target_llvm_type), name="tcast_ptr") + if not target_ptr: + if isinstance(target_arg, ast.Subscript): + target_ptr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(target_arg) + else: + target_ptr = self.HandleExprLlvm(target_arg) + Val = self.HandleExprLlvm(value_arg) + if target_ptr and Val: + if isinstance(target_ptr.type, ir.PointerType): + ValToStore = Val + pointee = target_ptr.type.pointee + if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8: + if isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8: + ValToStore = Val + elif isinstance(Val.type, ir.IntType): + ValToStore = Gen.builder.inttoptr(Val, pointee, name="int_to_ptr_set") + elif isinstance(pointee, ir.IntType): + if isinstance(Val.type, ir.ArrayType) and isinstance(Val.type.element, ir.IntType) and Val.type.element.width == 8: + zero = ir.Constant(ir.IntType(32), 0) + value_ptr = Gen.builder.gep(Val, [zero, zero], name="value_ptr") + ValToStore = Gen._load(value_ptr, name="Load_value") + elif isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8: + ValToStore = Gen._load(Val, name="Load_char_value") + if isinstance(ValToStore.type, ir.IntType) and isinstance(pointee, ir.IntType): + if ValToStore.type.width < pointee.width: + ValToStore = Gen.builder.zext(ValToStore, pointee, name="zext_set") + elif ValToStore.type.width > pointee.width: + ValToStore = Gen.builder.trunc(ValToStore, pointee, name="trunc_set") + elif Val.type != pointee: + if isinstance(pointee, ir.PointerType) and isinstance(Val.type, ir.PointerType): + ValToStore = Gen.builder.bitcast(Val, pointee, name="bitcast_set") + Gen._store(ValToStore, target_ptr) + return ir.Constant(ir.IntType(32), 1) + + def _HandleCLoadLlvm(self, Node): + Gen = self.Trans.LlvmGen + if len(Node.args) < 2: + return ir.Constant(ir.IntType(32), 0) + src_val = self.HandleExprLlvm(Node.args[0]) + dst_val = self.HandleExprLlvm(Node.args[1]) + if not src_val or not dst_val: + return ir.Constant(ir.IntType(32), 0) + if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType): + return ir.Constant(ir.IntType(32), 0) + Loaded = Gen._load(src_val, name="cLoad_src") + if Loaded is None: + return ir.Constant(ir.IntType(32), 0) + pointee = dst_val.type.pointee + val_to_store = Loaded + if isinstance(pointee, ir.IntType) and isinstance(Loaded.type, ir.IntType): + if Loaded.type.width < pointee.width: + val_to_store = Gen.builder.zext(Loaded, pointee, name="cLoad_zext") + elif Loaded.type.width > pointee.width: + val_to_store = Gen.builder.trunc(Loaded, pointee, name="cLoad_trunc") + elif isinstance(pointee, ir.PointerType) and isinstance(Loaded.type, ir.PointerType): + val_to_store = Gen.builder.bitcast(Loaded, pointee, name="cLoad_bitcast") + elif Loaded.type != pointee: + target_ptr = Gen.builder.bitcast(src_val, ir.PointerType(pointee), name="cLoad_cast") + Loaded = Gen._load(target_ptr, name="cLoad_casted") + if Loaded is None: + return ir.Constant(ir.IntType(32), 0) + val_to_store = Loaded + Gen._store(val_to_store, dst_val) + return ir.Constant(ir.IntType(32), 1) + + def _HandleCDerefLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not Node.args: + return ir.Constant(ir.IntType(64), 0) + arg_val = self.HandleExprLlvm(Node.args[0]) + if arg_val is None: + return ir.Constant(ir.IntType(32), 0) + if isinstance(arg_val.type, ir.PointerType): + Loaded = Gen._load(arg_val, name="deref") + if Loaded is not None: + return Loaded + return arg_val + + def _HandleCPtrToIntLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not Node.args: + return ir.Constant(ir.IntType(64), 0) + arg_val = self.HandleExprLlvm(Node.args[0]) + if arg_val is None: + return ir.Constant(ir.IntType(64), 0) + if isinstance(arg_val.type, ir.PointerType): + return Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptrtoint_result") + if isinstance(arg_val.type, ir.IntType): + if arg_val.type.width < 64: + return Gen.builder.zext(arg_val, ir.IntType(64), name="zext_ptrtoint") + elif arg_val.type.width > 64: + return Gen.builder.trunc(arg_val, ir.IntType(64), name="trunc_ptrtoint") + return arg_val + return ir.Constant(ir.IntType(64), 0) + + +class TSpecialCallHandle(BaseHandle): + + @staticmethod + def _ResolveTAttrToCName(attr: str) -> str: + from lib.includes.t import CTypeRegistry + ctype_cls = CTypeRegistry.GetClassByName(attr) + if ctype_cls is not None: + try: + inst = ctype_cls() + cname = getattr(inst, 'CName', '') + if cname: + return cname + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"处理函数调用失败: {_e}", "Exception") + return None + + def _HandleTSpecialCallLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not Node.args: + return None + attr = Node.func.attr + + if attr == 'CType': + return self._HandleCTypeLlvm(Node) + + target_type = self._ResolveTAttrToCName(attr) + if target_type is not None: + IsPtr_cast = False + if len(Node.args) >= 2: + second_arg = Node.args[1] + if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and second_arg.value.id == 't' and second_arg.attr == 'CPtr': + IsPtr_cast = True + elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr': + IsPtr_cast = True + if IsPtr_cast: + return self._HandleTPtrCastLlvm(Node, attr) + if target_type == 'void': + target_type = 'void *' + return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type) + return None + + def _HandleCTypeLlvm(self, Node): + Gen = self.Trans.LlvmGen + arg_val = self.HandleExprLlvm(Node.args[0]) + if not arg_val: + return None + target_type_str = 'unsigned long long' + if len(Node.args) >= 2: + type_parts = [] + ptr_count = 0 + for i in range(1, len(Node.args)): + type_arg = Node.args[i] + if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't': + type_attr = type_arg.attr + _PREFIX_MAP = { + 'CUnsigned': 'unsigned', 'CSigned': 'signed', + 'CConst': 'const', 'CVolatile': 'volatile', + } + if type_attr in _PREFIX_MAP: + type_parts.append(_PREFIX_MAP[type_attr]) + elif type_attr in ('CPtr', 'CArrayPtr'): + ptr_count += 1 + else: + resolved = self._ResolveTAttrToCName(type_attr) + if resolved is not None: + type_parts.append(resolved) + if type_parts: + target_type_str = ' '.join(type_parts) + if ptr_count > 0: + target_type_str += ' ' + '*' * ptr_count + if isinstance(arg_val.type, ir.PointerType): + int_val = Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptr_to_int") + return int_val + return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str) + + def _HandleTPtrCastLlvm(self, Node, attr): + Gen = self.Trans.LlvmGen + from lib.includes.t import CTypeRegistry + if attr in ('CChar', 'CUnsignedChar'): + first_arg = Node.args[0] + if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and first_arg.func.value.id == 't' and first_arg.func.attr == 'CInt' and first_arg.args: + inner_val = self.HandleExprLlvm(first_arg.args[0]) + if isinstance(inner_val.type, ir.PointerType): + return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint") + expr_val = self.HandleExprLlvm(Node.args[0]) + if isinstance(expr_val.type, ir.IntType) and expr_val.type.width == 8: + var = Gen._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"c{attr.lower()}_ptr") + zero = ir.Constant(ir.IntType(32), 0) + char_ptr = Gen.builder.gep(var, [zero, zero], name="char_ptr") + Gen._store(expr_val, char_ptr) + null_char = ir.Constant(ir.IntType(8), 0) + null_ptr = Gen.builder.gep(var, [zero, ir.Constant(ir.IntType(32), 1)], name="null_ptr") + Gen._store(null_char, null_ptr) + return char_ptr + elif isinstance(expr_val.type, ir.PointerType): + if isinstance(expr_val.type.pointee, ir.PointerType): + Loaded_ptr = Gen._load(expr_val, name="load_ptr") + if isinstance(Loaded_ptr.type, ir.PointerType) and isinstance(Loaded_ptr.type.pointee, ir.IntType) and Loaded_ptr.type.pointee.width == 8: + return Loaded_ptr + if isinstance(expr_val.type.pointee, ir.IntType) and expr_val.type.pointee.width == 8: + return expr_val + return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(8)), name="cast_to_char_ptr") + elif isinstance(expr_val.type, ir.IntType): + if expr_val.type.width == 32: + expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") + return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(8)), name=f"inttoptr_c{attr.lower()}") + return Gen.emit_constant(0, 'int') + elif attr == 'CVoid': + return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], 'void *') + elif attr == 'CInt': + expr_val = self.HandleExprLlvm(Node.args[0]) + if expr_val: + if isinstance(expr_val.type, ir.IntType): + if expr_val.type.width < 64: + expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") + return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr") + return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr") + else: + ctype_cls = CTypeRegistry.GetClassByName(attr) + if ctype_cls is not None: + llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + target_type = Gen._type_str_to_llvm(llvm_str) + if target_type and isinstance(target_type, (ir.IntType, ir.FloatType, ir.DoubleType)): + target_ptr_type = ir.PointerType(target_type) + expr_val = self.HandleExprLlvm(Node.args[0]) + if expr_val: + if isinstance(expr_val.type, ir.IntType): + if expr_val.type.width < 64: + expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64") + return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr") + return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr") + return None diff --git a/lib/core/Handles/HandlesTry.py b/lib/core/Handles/HandlesTry.py index 93e63d4..0c8cc86 100644 --- a/lib/core/Handles/HandlesTry.py +++ b/lib/core/Handles/HandlesTry.py @@ -1,211 +1,211 @@ -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, EXCEPTION_CODE_MAP -import ast -import llvmlite.ir as ir - - -class TryHandle(BaseHandle): - def _get_exception_type_code(self, type_node): - if isinstance(type_node, ast.Name): - name = type_node.id - if name in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[name] - if name in self.Trans.exception_registry: - return self.Trans.exception_registry[name] - return 1 - if isinstance(type_node, ast.Attribute): - name = type_node.attr - if name in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[name] - if name in self.Trans.exception_registry: - return self.Trans.exception_registry[name] - return 1 - if isinstance(type_node, ast.Tuple): - for elt in type_node.elts: - code = self._get_exception_type_code(elt) - if code != 1: - return code - return 1 - return 1 - - def _get_exception_name(self, type_node): - if isinstance(type_node, ast.Name): - return type_node.id - if isinstance(type_node, ast.Attribute): - return type_node.attr - return None - - def _get_all_match_codes(self, type_node): - name = self._get_exception_name(type_node) - if name is None: - return [self._get_exception_type_code(type_node)] - if name not in self.Trans.exception_registry: - return [self._get_exception_type_code(type_node)] - codes = [self.Trans.exception_registry[name]] - self._collect_descendant_codes(name, codes) - return codes - - def _collect_descendant_codes(self, parent_name, codes): - for child_name, parent in self.Trans.exception_parents.items(): - if parent == parent_name: - child_code = self.Trans.exception_registry.get(child_name) - if child_code is not None and child_code not in codes: - codes.append(child_code) - self._collect_descendant_codes(child_name, codes) - - def _HandleTryLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Gen.func: - return - exception_code = Gen._alloca_entry(ir.IntType(32), name="eh_code") - eh_message = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name="eh_message") - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_message) - HasFinally = bool(Node.finalbody) - if HasFinally: - Gen.eh_finally_stack.append((None, None, None)) - else: - Gen.eh_finally_stack.append(None) - DispatchBB = Gen.func.append_basic_block(name="try.dispatch") - AfterBB = Gen.func.append_basic_block(name="try.after") - except_blocks = [] - for i, handler in enumerate(Node.handlers): - ExcTypeCodes = [1] - if handler.type: - ExcTypeCodes = self._get_all_match_codes(handler.type) - ExceptBB = Gen.func.append_basic_block(name=f"try.except_{i}") - Gen.eh_except_block_stack.append((DispatchBB, None, exception_code, eh_message)) - except_blocks.append((ExceptBB, ExcTypeCodes, handler)) - TryBB = Gen.func.append_basic_block(name="try.body") - ElseBB = None - if Node.orelse: - ElseBB = Gen.func.append_basic_block(name="try.else") - Gen.builder.branch(TryBB) - Gen.builder.position_at_start(TryBB) - self.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - if ElseBB: - Gen.builder.branch(ElseBB) - else: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(DispatchBB) - eh_code_val = Gen._load(exception_code, name="load_eh_code") - next_check_bb = None - handler_var_map = {} - UnhandledBB = Gen.func.append_basic_block(name="try.unhandled") - for i, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): - MatchBB = Gen.func.append_basic_block(name=f"try.match_{i}") - if i > 0 and next_check_bb is not None: - Gen.builder.position_at_start(next_check_bb) - eh_code_val = Gen._load(exception_code, name=f"load_eh_code_{i}") - if handler.type is None: - Gen.builder.branch(MatchBB) - else: - match_cond = None - for code in ExcTypeCodes: - is_code_match = Gen.builder.icmp_signed('==', eh_code_val, ir.Constant(ir.IntType(32), code), name=f"eh_match_{i}_c{code}") - if match_cond is None: - match_cond = is_code_match - else: - match_cond = Gen.builder.or_(match_cond, is_code_match, name=f"eh_match_any_{i}") - if i < len(except_blocks) - 1: - next_check_bb = Gen.func.append_basic_block(name=f"try.check_{i}") - else: - next_check_bb = UnhandledBB - Gen.builder.cbranch(match_cond, MatchBB, next_check_bb) - Gen.builder.position_at_start(MatchBB) - if handler.name: - var_alloca = Gen._alloca_entry(ir.IntType(8).as_pointer(), name=handler.name) - eh_msg_val = Gen._load(eh_message, name=f"load_eh_msg_{handler.name}") - Gen._store(eh_msg_val, var_alloca) - handler_var_map[i] = (handler.name, var_alloca, Gen.variables.get(handler.name)) - Gen.builder.branch(ExceptBB) - Gen.builder.position_at_start(UnhandledBB) - eh_msg_out_arg = None - eh_code_out_arg = None - if Gen.func and len(Gen.func.args) > 0: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_out_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_out_arg = arg - if eh_msg_out_arg is not None and eh_code_out_arg is not None: - eh_msg_val = Gen._load(eh_message, name="load_eh_msg_propagate") - eh_code_val_prop = Gen._load(exception_code, name="load_eh_code_propagate") - Gen._store(eh_msg_val, eh_msg_out_arg) - Gen._store(eh_code_val_prop, eh_code_out_arg) - ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None - if isinstance(ret_type, ir.IdentifiedStructType): - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ - ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) - else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) - else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - Gen.builder.ret(zero_val) - elif isinstance(ret_type, ir.PointerType): - Gen.builder.ret(ir.Constant(ret_type, None)) - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): - Gen.builder.ret(ir.Constant(ret_type, 0.0)) - elif isinstance(ret_type, ir.IntType): - Gen.builder.ret(ir.Constant(ret_type, 1)) - elif isinstance(ret_type, ir.VoidType): - Gen.builder.ret_void() - else: - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - Gen.builder.branch(AfterBB) - for idx, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): - Gen.builder.position_at_start(ExceptBB) - old_var = None - if idx in handler_var_map: - hname, var_alloca, old_var = handler_var_map[idx] - Gen.variables[hname] = var_alloca - self.HandleBodyLlvm(handler.body) - if idx in handler_var_map: - hname, _, old_var = handler_var_map[idx] - if old_var is not None: - Gen.variables[hname] = old_var - elif hname in Gen.variables: - del Gen.variables[hname] - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.eh_except_block_stack.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) - if HasFinally: - Gen.eh_finally_stack.pop() - if Node.finalbody: - FinallyBB = Gen.func.append_basic_block(name="try.finally") - pending_ret_flag = Gen._alloca_entry(ir.IntType(32), name="pending_ret_flag") - pending_ret_val = Gen._alloca_entry(ir.IntType(32), name="pending_ret_val") if Gen.func.type.pointee.return_type == ir.IntType(32) else None - Gen.eh_finally_stack.append((FinallyBB, pending_ret_flag, pending_ret_val)) - Gen.builder.branch(FinallyBB) - Gen.builder.position_at_start(FinallyBB) - Gen._store(ir.Constant(ir.IntType(32), 0), pending_ret_flag) - self.HandleBodyLlvm(Node.finalbody) - if Gen.eh_finally_stack: - _, pending_ret_flag, pending_ret_val = Gen.eh_finally_stack[-1] - Gen.eh_finally_stack.pop() - ret_flag_val = Gen._load(pending_ret_flag, name="load_ret_flag") - ret_flag_is_set = Gen.builder.icmp_signed('!=', ret_flag_val, ir.Constant(ir.IntType(32), 0), name="check_ret_flag") - RetBB = Gen.func.append_basic_block(name="finally.ret") - ContinueBB = Gen.func.append_basic_block(name="try.continue") - Gen.builder.cbranch(ret_flag_is_set, RetBB, ContinueBB) - Gen.builder.position_at_start(RetBB) - if pending_ret_val: - ret_val = Gen._load(pending_ret_val, name="load_ret_val") - Gen.builder.ret(ret_val) - else: - Gen.builder.ret_void() +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, EXCEPTION_CODE_MAP +import ast +import llvmlite.ir as ir + + +class TryHandle(BaseHandle): + def _get_exception_type_code(self, type_node): + if isinstance(type_node, ast.Name): + name = type_node.id + if name in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[name] + if name in self.Trans.exception_registry: + return self.Trans.exception_registry[name] + return 1 + if isinstance(type_node, ast.Attribute): + name = type_node.attr + if name in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[name] + if name in self.Trans.exception_registry: + return self.Trans.exception_registry[name] + return 1 + if isinstance(type_node, ast.Tuple): + for elt in type_node.elts: + code = self._get_exception_type_code(elt) + if code != 1: + return code + return 1 + return 1 + + def _get_exception_name(self, type_node): + if isinstance(type_node, ast.Name): + return type_node.id + if isinstance(type_node, ast.Attribute): + return type_node.attr + return None + + def _get_all_match_codes(self, type_node): + name = self._get_exception_name(type_node) + if name is None: + return [self._get_exception_type_code(type_node)] + if name not in self.Trans.exception_registry: + return [self._get_exception_type_code(type_node)] + codes = [self.Trans.exception_registry[name]] + self._collect_descendant_codes(name, codes) + return codes + + def _collect_descendant_codes(self, parent_name, codes): + for child_name, parent in self.Trans.exception_parents.items(): + if parent == parent_name: + child_code = self.Trans.exception_registry.get(child_name) + if child_code is not None and child_code not in codes: + codes.append(child_code) + self._collect_descendant_codes(child_name, codes) + + def _HandleTryLlvm(self, Node): + Gen = self.Trans.LlvmGen + if not Gen.func: + return + exception_code = Gen._allocaEntry(ir.IntType(32), name="eh_code") + eh_message = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_message") + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_message) + HasFinally = bool(Node.finalbody) + if HasFinally: + Gen.eh_finally_stack.append((None, None, None)) + else: + Gen.eh_finally_stack.append(None) + DispatchBB = Gen.func.append_basic_block(name="try.dispatch") + AfterBB = Gen.func.append_basic_block(name="try.after") + except_blocks = [] + for i, handler in enumerate(Node.handlers): + ExcTypeCodes = [1] + if handler.type: + ExcTypeCodes = self._get_all_match_codes(handler.type) + ExceptBB = Gen.func.append_basic_block(name=f"try.except_{i}") + Gen.eh_except_block_stack.append((DispatchBB, None, exception_code, eh_message)) + except_blocks.append((ExceptBB, ExcTypeCodes, handler)) + TryBB = Gen.func.append_basic_block(name="try.body") + ElseBB = None + if Node.orelse: + ElseBB = Gen.func.append_basic_block(name="try.else") + Gen.builder.branch(TryBB) + Gen.builder.position_at_start(TryBB) + self.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + if ElseBB: + Gen.builder.branch(ElseBB) + else: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(DispatchBB) + eh_code_val = Gen._load(exception_code, name="Load_eh_code") + next_check_bb = None + handler_var_map = {} + UnhandledBB = Gen.func.append_basic_block(name="try.unhandled") + for i, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): + MatchBB = Gen.func.append_basic_block(name=f"try.match_{i}") + if i > 0 and next_check_bb is not None: + Gen.builder.position_at_start(next_check_bb) + eh_code_val = Gen._load(exception_code, name=f"Load_eh_code_{i}") + if handler.type is None: + Gen.builder.branch(MatchBB) + else: + match_cond = None + for code in ExcTypeCodes: + is_code_match = Gen.builder.icmp_signed('==', eh_code_val, ir.Constant(ir.IntType(32), code), name=f"eh_match_{i}_c{code}") + if match_cond is None: + match_cond = is_code_match + else: + match_cond = Gen.builder.or_(match_cond, is_code_match, name=f"eh_match_any_{i}") + if i < len(except_blocks) - 1: + next_check_bb = Gen.func.append_basic_block(name=f"try.check_{i}") + else: + next_check_bb = UnhandledBB + Gen.builder.cbranch(match_cond, MatchBB, next_check_bb) + Gen.builder.position_at_start(MatchBB) + if handler.name: + var_alloca = Gen._allocaEntry(ir.IntType(8).as_pointer(), name=handler.name) + eh_msg_val = Gen._load(eh_message, name=f"Load_eh_msg_{handler.name}") + Gen._store(eh_msg_val, var_alloca) + handler_var_map[i] = (handler.name, var_alloca, Gen.variables.get(handler.name)) + Gen.builder.branch(ExceptBB) + Gen.builder.position_at_start(UnhandledBB) + eh_msg_out_arg = None + eh_code_out_arg = None + if Gen.func and len(Gen.func.args) > 0: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_out_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_out_arg = arg + if eh_msg_out_arg is not None and eh_code_out_arg is not None: + eh_msg_val = Gen._load(eh_message, name="Load_eh_msg_propagate") + eh_code_val_prop = Gen._load(exception_code, name="Load_eh_code_propagate") + Gen._store(eh_msg_val, eh_msg_out_arg) + Gen._store(eh_code_val_prop, eh_code_out_arg) + ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None + if isinstance(ret_type, ir.IdentifiedStructType): + if ret_type.elements: + zero_val = ir.Constant(ret_type, [ + ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) + else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) + else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + Gen.builder.ret(zero_val) + elif isinstance(ret_type, ir.PointerType): + Gen.builder.ret(ir.Constant(ret_type, None)) + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): + Gen.builder.ret(ir.Constant(ret_type, 0.0)) + elif isinstance(ret_type, ir.IntType): + Gen.builder.ret(ir.Constant(ret_type, 1)) + elif isinstance(ret_type, ir.VoidType): + Gen.builder.ret_void() + else: + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + Gen.builder.branch(AfterBB) + for idx, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): + Gen.builder.position_at_start(ExceptBB) + old_var = None + if idx in handler_var_map: + hname, var_alloca, old_var = handler_var_map[idx] + Gen.variables[hname] = var_alloca + self.HandleBodyLlvm(handler.body) + if idx in handler_var_map: + hname, _, old_var = handler_var_map[idx] + if old_var is not None: + Gen.variables[hname] = old_var + elif hname in Gen.variables: + del Gen.variables[hname] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.eh_except_block_stack.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) + if HasFinally: + Gen.eh_finally_stack.pop() + if Node.finalbody: + FinallyBB = Gen.func.append_basic_block(name="try.finally") + pending_ret_flag = Gen._allocaEntry(ir.IntType(32), name="pending_ret_flag") + pending_ret_val = Gen._allocaEntry(ir.IntType(32), name="pending_ret_val") if Gen.func.type.pointee.return_type == ir.IntType(32) else None + Gen.eh_finally_stack.append((FinallyBB, pending_ret_flag, pending_ret_val)) + Gen.builder.branch(FinallyBB) + Gen.builder.position_at_start(FinallyBB) + Gen._store(ir.Constant(ir.IntType(32), 0), pending_ret_flag) + self.HandleBodyLlvm(Node.finalbody) + if Gen.eh_finally_stack: + _, pending_ret_flag, pending_ret_val = Gen.eh_finally_stack[-1] + Gen.eh_finally_stack.pop() + ret_flag_val = Gen._load(pending_ret_flag, name="Load_ret_flag") + ret_flag_is_set = Gen.builder.icmp_signed('!=', ret_flag_val, ir.Constant(ir.IntType(32), 0), name="check_ret_flag") + RetBB = Gen.func.append_basic_block(name="finally.ret") + ContinueBB = Gen.func.append_basic_block(name="try.continue") + Gen.builder.cbranch(ret_flag_is_set, RetBB, ContinueBB) + Gen.builder.position_at_start(RetBB) + if pending_ret_val: + ret_val = Gen._load(pending_ret_val, name="Load_ret_val") + Gen.builder.ret(ret_val) + else: + Gen.builder.ret_void() Gen.builder.position_at_start(ContinueBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index 09ccf98..cf9f676 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -113,7 +113,7 @@ class HandlesTypeMerge(BaseHandle): # 解析 import 别名: 如 import fat32_types as types -> types -> fat32_types if ModulePath: - import_aliases = getattr(self.Trans, '_import_aliases', {}) + import_aliases = getattr(self.Trans, '_ImportAliases', {}) if ModulePath in import_aliases: ModulePath = import_aliases[ModulePath] else: diff --git a/lib/core/Handles/HandlesWhile.py b/lib/core/Handles/HandlesWhile.py index aecbbd8..754b026 100644 --- a/lib/core/Handles/HandlesWhile.py +++ b/lib/core/Handles/HandlesWhile.py @@ -1,54 +1,54 @@ -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): - Gen = self.Trans.LlvmGen - if Gen._direct_values: - for var_name in list(Gen._direct_values.keys()): - OldVal = Gen._direct_values.pop(var_name) - if var_name not in Gen.variables or Gen.variables.get(var_name) is None: - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = 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 = Gen.func.append_basic_block(name="while.cond") - BodyBB = Gen.func.append_basic_block(name="while.body") - ElseBB = Gen.func.append_basic_block(name="while.else") if Node.orelse else None - AfterBB = 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 = 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._zero_const(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) +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): + Gen = self.Trans.LlvmGen + if Gen._direct_values: + for var_name in list(Gen._direct_values.keys()): + OldVal = Gen._direct_values.pop(var_name) + if var_name not in Gen.variables or Gen.variables.get(var_name) is None: + saved_block = Gen.builder.block + entry_block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var = 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 = Gen.func.append_basic_block(name="while.cond") + BodyBB = Gen.func.append_basic_block(name="while.body") + ElseBB = Gen.func.append_basic_block(name="while.else") if Node.orelse else None + AfterBB = 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 = 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) diff --git a/lib/core/Handles/HandlesWith.py b/lib/core/Handles/HandlesWith.py index f6eae1d..1b1fc34 100644 --- a/lib/core/Handles/HandlesWith.py +++ b/lib/core/Handles/HandlesWith.py @@ -1,138 +1,138 @@ -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 ast -import llvmlite.ir as ir - - -class WithHandle(BaseHandle): - def _HandleWithLlvm(self, Node): - Gen = self.Trans.LlvmGen - for item in Node.items: - context_expr = item.context_expr - asname = None - target = getattr(item, 'optional_vars', getattr(item, 'target', getattr(item, 'asname', None))) - if target and isinstance(target, ast.Name): - asname = target.id - ClassName = None - if isinstance(context_expr, ast.Call): - if isinstance(context_expr.func, ast.Name): - ClassName = context_expr.func.id - elif isinstance(context_expr.func, ast.Attribute): - ClassName = context_expr.func.attr - if ClassName and ClassName not in Gen.structs: - if ClassName in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[ClassName] - if getattr(SymInfo, 'IsStruct', False) or getattr(SymInfo, 'IsRenum', False): - pass - else: - ClassName = None - else: - ClassName = None - elif isinstance(context_expr, ast.Name): - VarName = context_expr.id - if VarName in Gen.var_struct_class: - ClassName = Gen.var_struct_class[VarName] - ctx_val = self.HandleExprLlvm(context_expr) - if not ctx_val: - continue - original_ctx_val = ctx_val - if ClassName and isinstance(ctx_val.type, ir.PointerType): - pointee = ctx_val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - ClassName = CN - StructPtrType = ir.PointerType(Gen.structs[ClassName]) if ClassName and ClassName in Gen.structs else None - if StructPtrType and isinstance(ctx_val.type, ir.PointerType) and ctx_val.type.pointee != Gen.structs.get(ClassName): - ctx_val = Gen.builder.bitcast(ctx_val, StructPtrType, name="cast_with_ctx") - ctx_alloca = Gen._alloca_entry(ctx_val.type, name="__with_ctx") - Gen._store(ctx_val, ctx_alloca) - Gen._unregister_temp_ptr(ctx_val) - if ClassName: - Gen.var_struct_class['__with_ctx'] = ClassName - Gen._var_to_heap_ptr['__with_ctx'] = ctx_val - original_asname_heap_ptr = Gen._var_to_heap_ptr.get(asname) if asname else None - ctx_is_var_ref = isinstance(context_expr, ast.Name) - enter_result = None - if ClassName: - EnterFuncName = f'{ClassName}.__enter__' - if EnterFuncName in Gen.functions: - ctx_loaded = Gen._load(ctx_alloca, name="__with_ctx") - enter_call = Gen.builder.call(Gen.functions[EnterFuncName], [ctx_loaded], name="call_enter") - enter_result = enter_call - if isinstance(enter_call.type, ir.PointerType): - pointee = enter_call.type.pointee - if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - enter_result = Gen._load(enter_call, name="enter_deref") - elif self._is_char_pointer(enter_call) and StructPtrType: - enter_result = Gen.builder.bitcast(enter_call, StructPtrType, name="cast_enter") - if asname and enter_result: - if isinstance(enter_result.type, ir.PointerType) and isinstance(enter_result.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(enter_result.type.pointee) - if found: - CN, ST = found - Gen.var_struct_class[asname] = CN - Gen._var_to_heap_ptr[asname] = enter_result - Gen._register_local_heap_ptr(enter_result, VarName=asname) - if asname in Gen._reg_values: - OldVal = Gen._reg_values[asname] - var = Gen._alloca_entry(OldVal.type, name=asname) - Gen._store(OldVal, var) - Gen.variables[asname] = var - del Gen._reg_values[asname] - if asname in Gen.variables and Gen.variables[asname] is not None: - VarPtr = Gen.variables[asname] - if VarPtr.type.pointee == enter_result.type: - Gen._store(enter_result, VarPtr) - elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): - CastedVal = Gen.builder.bitcast(enter_result, VarPtr.type.pointee, name=f"cast_{asname}") - Gen._store(CastedVal, VarPtr) - else: - NewVar = Gen._alloca(enter_result.type, name=asname) - Gen._store(enter_result, NewVar) - Gen.variables[asname] = NewVar - else: - Gen._reg_values[asname] = enter_result - Gen.variables[asname] = None - self.Trans.VarScopes.append({}) - if asname: - self.Trans.VarScopes[-1][asname] = True - self.HandleBodyLlvm(Node.body) - if self.Trans.VarScopes: - self.Trans.VarScopes.pop() - if ClassName: - ExitFuncName = f'{ClassName}.__exit__' - if ExitFuncName in Gen.functions: - ctx_loaded = Gen._load(ctx_alloca, name="__with_ctx") - Gen.builder.call(Gen.functions[ExitFuncName], [ctx_loaded], name="call_exit") - Gen._unregister_local_heap_ptr(original_ctx_val) - if ctx_val is not original_ctx_val: - Gen._unregister_local_heap_ptr(ctx_val) - if ctx_is_var_ref and original_asname_heap_ptr and original_asname_heap_ptr is not original_ctx_val and original_asname_heap_ptr is not ctx_val: - Gen._unregister_local_heap_ptr(original_asname_heap_ptr) - if '__with_ctx' in Gen._var_to_heap_ptr: - del Gen._var_to_heap_ptr['__with_ctx'] - if asname and enter_result is not None and isinstance(ctx_val.type, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): - ctx_int = Gen.builder.ptrtoint(ctx_val, ir.IntType(64), name="ctx_int") - enter_int = Gen.builder.ptrtoint(enter_result, ir.IntType(64), name="enter_int") - same_ptr = Gen.builder.icmp_unsigned('==', ctx_int, enter_int, name="same_ptr_check") - with_free_bb = Gen.func.append_basic_block("with_free_ctx") - with_skip_bb = Gen.func.append_basic_block("with_skip_free") - Gen.builder.cbranch(same_ptr, with_skip_bb, with_free_bb) - Gen.builder.position_at_start(with_free_bb) - raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") - free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) - Gen.builder.call(free_func, [raw]) - Gen.builder.branch(with_skip_bb) - Gen.builder.position_at_start(with_skip_bb) - Gen._unregister_local_heap_ptr(enter_result) - Gen._unregister_local_heap_ptr(original_ctx_val) - elif isinstance(ctx_val.type, ir.PointerType): - raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") - free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) - Gen.builder.call(free_func, [raw]) +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 ast +import llvmlite.ir as ir + + +class WithHandle(BaseHandle): + def _HandleWithLlvm(self, Node): + Gen = self.Trans.LlvmGen + for item in Node.items: + context_expr = item.context_expr + asname = None + target = getattr(item, 'optional_vars', getattr(item, 'target', getattr(item, 'asname', None))) + if target and isinstance(target, ast.Name): + asname = target.id + ClassName = None + if isinstance(context_expr, ast.Call): + if isinstance(context_expr.func, ast.Name): + ClassName = context_expr.func.id + elif isinstance(context_expr.func, ast.Attribute): + ClassName = context_expr.func.attr + if ClassName and ClassName not in Gen.structs: + if ClassName in self.Trans.SymbolTable: + SymInfo = self.Trans.SymbolTable[ClassName] + if getattr(SymInfo, 'IsStruct', False) or getattr(SymInfo, 'IsRenum', False): + pass + else: + ClassName = None + else: + ClassName = None + elif isinstance(context_expr, ast.Name): + VarName = context_expr.id + if VarName in Gen.var_struct_class: + ClassName = Gen.var_struct_class[VarName] + ctx_val = self.HandleExprLlvm(context_expr) + if not ctx_val: + continue + original_ctx_val = ctx_val + if ClassName and isinstance(ctx_val.type, ir.PointerType): + pointee = ctx_val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found = Gen.find_struct_by_pointee(pointee) + if found: + CN, ST = found + ClassName = CN + StructPtrType = ir.PointerType(Gen.structs[ClassName]) if ClassName and ClassName in Gen.structs else None + if StructPtrType and isinstance(ctx_val.type, ir.PointerType) and ctx_val.type.pointee != Gen.structs.get(ClassName): + ctx_val = Gen.builder.bitcast(ctx_val, StructPtrType, name="cast_with_ctx") + ctx_alloca = Gen._allocaEntry(ctx_val.type, name="__with_ctx") + Gen._store(ctx_val, ctx_alloca) + Gen._UnregisterTempPtr(ctx_val) + if ClassName: + Gen.var_struct_class['__with_ctx'] = ClassName + Gen._var_to_heap_ptr['__with_ctx'] = ctx_val + original_asname_heap_ptr = Gen._var_to_heap_ptr.get(asname) if asname else None + ctx_is_var_ref = isinstance(context_expr, ast.Name) + enter_result = None + if ClassName: + EnterFuncName = f'{ClassName}.__enter__' + if EnterFuncName in Gen.functions: + ctx_Loaded = Gen._load(ctx_alloca, name="__with_ctx") + enter_call = Gen.builder.call(Gen.functions[EnterFuncName], [ctx_Loaded], name="call_enter") + enter_result = enter_call + if isinstance(enter_call.type, ir.PointerType): + pointee = enter_call.type.pointee + if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + enter_result = Gen._load(enter_call, name="enter_deref") + elif self._is_char_pointer(enter_call) and StructPtrType: + enter_result = Gen.builder.bitcast(enter_call, StructPtrType, name="cast_enter") + if asname and enter_result: + if isinstance(enter_result.type, ir.PointerType) and isinstance(enter_result.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found = Gen.find_struct_by_pointee(enter_result.type.pointee) + if found: + CN, ST = found + Gen.var_struct_class[asname] = CN + Gen._var_to_heap_ptr[asname] = enter_result + Gen._register_local_heap_ptr(enter_result, VarName=asname) + if asname in Gen._reg_values: + OldVal = Gen._reg_values[asname] + var = Gen._allocaEntry(OldVal.type, name=asname) + Gen._store(OldVal, var) + Gen.variables[asname] = var + del Gen._reg_values[asname] + if asname in Gen.variables and Gen.variables[asname] is not None: + VarPtr = Gen.variables[asname] + if VarPtr.type.pointee == enter_result.type: + Gen._store(enter_result, VarPtr) + elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): + CastedVal = Gen.builder.bitcast(enter_result, VarPtr.type.pointee, name=f"cast_{asname}") + Gen._store(CastedVal, VarPtr) + else: + NewVar = Gen._alloca(enter_result.type, name=asname) + Gen._store(enter_result, NewVar) + Gen.variables[asname] = NewVar + else: + Gen._reg_values[asname] = enter_result + Gen.variables[asname] = None + self.Trans.VarScopes.append({}) + if asname: + self.Trans.VarScopes[-1][asname] = True + self.HandleBodyLlvm(Node.body) + if self.Trans.VarScopes: + self.Trans.VarScopes.pop() + if ClassName: + ExitFuncName = f'{ClassName}.__exit__' + if ExitFuncName in Gen.functions: + ctx_Loaded = Gen._load(ctx_alloca, name="__with_ctx") + Gen.builder.call(Gen.functions[ExitFuncName], [ctx_Loaded], name="call_exit") + Gen._unregister_local_heap_ptr(original_ctx_val) + if ctx_val is not original_ctx_val: + Gen._unregister_local_heap_ptr(ctx_val) + if ctx_is_var_ref and original_asname_heap_ptr and original_asname_heap_ptr is not original_ctx_val and original_asname_heap_ptr is not ctx_val: + Gen._unregister_local_heap_ptr(original_asname_heap_ptr) + if '__with_ctx' in Gen._var_to_heap_ptr: + del Gen._var_to_heap_ptr['__with_ctx'] + if asname and enter_result is not None and isinstance(ctx_val.type, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): + ctx_int = Gen.builder.ptrtoint(ctx_val, ir.IntType(64), name="ctx_int") + enter_int = Gen.builder.ptrtoint(enter_result, ir.IntType(64), name="enter_int") + same_ptr = Gen.builder.icmp_unsigned('==', ctx_int, enter_int, name="same_ptr_check") + with_free_bb = Gen.func.append_basic_block("with_free_ctx") + with_skip_bb = Gen.func.append_basic_block("with_skip_free") + Gen.builder.cbranch(same_ptr, with_skip_bb, with_free_bb) + Gen.builder.position_at_start(with_free_bb) + raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") + free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) + Gen.builder.call(free_func, [raw]) + Gen.builder.branch(with_skip_bb) + Gen.builder.position_at_start(with_skip_bb) + Gen._unregister_local_heap_ptr(enter_result) + Gen._unregister_local_heap_ptr(original_ctx_val) + elif isinstance(ctx_val.type, ir.PointerType): + raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") + free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) + Gen.builder.call(free_func, [raw]) Gen._unregister_local_heap_ptr(original_ctx_val) \ No newline at end of file diff --git a/lib/core/Handles/__init__.py b/lib/core/Handles/__init__.py index ba56367..b7c469e 100644 --- a/lib/core/Handles/__init__.py +++ b/lib/core/Handles/__init__.py @@ -27,6 +27,6 @@ from .HandlesTry import TryHandle from .HandlesAssert import AssertHandle from .HandlesRaise import RaiseHandle from .HandlesMatch import MatchHandle -from .HandlesClassDef import ClassHandle +from .HandlesClassDef import ClassHandle from .HandlesFunctions import FunctionHandle -from .HandlesImports import ImportHandle +from .HandlesImports import ImportHandle diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py new file mode 100644 index 0000000..e944925 --- /dev/null +++ b/lib/core/LLVMCG/BaseGen.py @@ -0,0 +1,412 @@ +from __future__ import annotations +import re +import ast +import os +import hashlib +import llvmlite.ir as ir +from llvmlite.ir.values import _Undefined + + +class VaArgInstruction(ir.Instruction): + def descr(self, buf): + ptr = self.operands[0] + buf.append("va_arg {0} {1}, {2}\n".format( + ptr.type, ptr.get_reference(), self.type)) + + +class BaseGenMixin: + + @staticmethod + def _parse_triple(triple): + """解析目标三元组,返回平台信息字典""" + info = { + 'is_windows': False, 'is_linux': False, 'is_macos': False, + 'is_x86_64': False, 'is_arm64': False, 'is_32bit': False, + 'ptr_size': 8, 'long_size': 8, 'wchar_t_size': 32, + } + if not triple: + return info + triple_lower = triple.lower() + # 检测操作系统 + if 'windows' in triple_lower or 'win32' in triple_lower or 'mingw' in triple_lower or 'msvc' in triple_lower or 'cygwin' in triple_lower: + info['is_windows'] = True + # Windows LLP64: long = 32 位, wchar_t = 16 位 + info['long_size'] = 32 + info['wchar_t_size'] = 16 + elif 'linux' in triple_lower: + info['is_linux'] = True + elif 'darwin' in triple_lower or 'macos' in triple_lower or 'apple' in triple_lower: + info['is_macos'] = True + # 检测架构 + if 'x86_64' in triple_lower or 'amd64' in triple_lower or 'x64' in triple_lower: + info['is_x86_64'] = True + elif 'aarch64' in triple_lower or 'arm64' in triple_lower: + info['is_arm64'] = True + elif 'i386' in triple_lower or 'i686' in triple_lower or 'arm' in triple_lower: + info['is_32bit'] = True + info['ptr_size'] = 4 + info['long_size'] = 32 + if info['is_windows']: + info['wchar_t_size'] = 16 + else: + info['wchar_t_size'] = 32 + return info + + def __init__(self, triple=None, datalayout=None): + self.module = ir.Module(name="transpyc_module") + if triple: + self.module.triple = triple + else: + self.module.triple = "x86_64-none-elf" + if datalayout: + self.module.data_layout = datalayout + else: + self.module.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + + # 解析目标平台信息 + self._platform_info = self._parse_triple(self.module.triple) + self.ptr_size = self._platform_info['ptr_size'] + # 根据目标平台配置 t 模块中的平台相关类型大小 + import t as _t + _t.configure_platform(self.module.triple) + self.builder = None + self.func = None + self.functions = {} + self.variables = {} + self._direct_values = {} + self._reg_values = {} + self.var_signedness = {} + self._unsigned_results = {} + self.string_const_counter = 0 + self.Vtables = {} + self.class_methods = {} + self.class_members = {} + self.class_member_defaults = {} + self.class_member_signeds = {} + self.class_member_bitfields = {} + self.class_member_byteorders = {} + self.class_member_element_class = {} + self.class_member_bitoffsets = {} + self.structs = {} + self.typedef_int_widths = {} # typedef名称 -> 底层整数位宽 (如 'UINT' -> 32, 'BYTE' -> 8) + self._cross_module_vtable_classes = set() + self.class_vtable = set() + self.class_parent = {} + # Store member annotations for deferred type resolution (cross-module class references) + self.class_member_annotations = {} + self.loop_break_targets = [] + self.loop_continue_targets = [] + self.eh_jmp_buf_stack = [] + self.eh_except_block_stack = [] + self.eh_finally_stack = [] + self.global_vars = set() + self.nonlocal_params = {} + self._variable_scope_stack = [] # Stack of outer scope variables for nested function nonlocal lookup + self.var_struct_class = {} + self.global_struct_class = {} + self.var_type_info = {} + self.var_const_flags = {} + self._current_source_file = None + self._current_source_lines = [] + self._ns_cache = {} + self._type_cache = {} + self._typedef_cache = {} + self._func_sig_cache = {} + self.var_type_assignments = {} + self._temp_struct_ptrs = [] + self._stop_iter_flag_param = None + self._local_heap_ptrs = [] + self._var_to_heap_ptr = {} + self.known_return_types = {} + self._current_lineno = 0 + self._current_node_info = "" + self.module_sha1 = None + self.ModuleSha1Map = {} + self._temp_dir = None + self._export_funcs = set() + self._export_extern_funcs = set() + self._current_module_func_names = set() + self.class_packed = set() + self._define_constants = {} + pi = self._platform_info + # 根据目标平台设置宏(声明式,从三元组推导) + if pi['is_windows']: + self._define_constants['_WIN32'] = 1 + if not pi['is_32bit']: + self._define_constants['_WIN64'] = 1 + self._define_constants['WIN64'] = 1 + self._define_constants['WIN32'] = 1 + if pi['is_linux']: + self._define_constants['__linux__'] = 1 + if pi['is_macos']: + self._define_constants['__APPLE__'] = 1 + self._define_constants['__MACH__'] = 1 + if pi['is_x86_64']: + self._define_constants['__x86_64__'] = 1 + self._define_constants['__x86_64'] = 1 + self._define_constants['_M_X64'] = 1 + elif pi['is_arm64']: + self._define_constants['__aarch64__'] = 1 + self._define_constants['_M_ARM64'] = 1 + if not pi['is_32bit'] and pi['is_linux']: + self._define_constants['__LP64__'] = 1 + elif pi['is_32bit']: + self._define_constants['_ILP32'] = 1 + self._define_constants['SIZEOF_VOID_P'] = pi['ptr_size'] + self._define_constants['__SIZEOF_POINTER__'] = pi['ptr_size'] + + def find_struct_by_pointee(self, pointee): + """根据 pointee 类型查找匹配的结构体,返回 (class_name, struct_type) 或 None""" + for class_name, struct_type in self.structs.items(): + if pointee == struct_type: + return (class_name, struct_type) + return None + + def _get_or_create_struct(self, name, source_sha1=None, packed=False): + clean_name = name.replace(' *', '').replace('*', '').replace(' ', '_').replace('const', 'const_').replace('volatile', 'volatile_') + if clean_name in self.structs: + existing = self.structs[clean_name] + if packed and isinstance(existing, ir.IdentifiedStructType) and not existing.packed: + existing.packed = True + return existing + if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}: + return ir.IntType(8) + if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable: + Entry = self.SymbolTable[clean_name] + if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: + resolved_str = self._resolve_typedef(clean_name) + if resolved_str != clean_name: + return self._type_str_to_llvm(resolved_str) + if hasattr(Entry, 'BaseType') and Entry.BaseType: + from lib.includes import t as _t + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: + resolved = self._resolve_ctype_to_str(Entry) + if resolved: + return self._type_str_to_llvm(resolved) + if hasattr(Entry, 'IsRenum') and Entry.IsRenum: + if clean_name in self.structs: + return self.structs[clean_name] + if hasattr(Entry, 'IsEnum') and Entry.IsEnum: + return ir.IntType(32) + if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + return ir.IntType(32) + if hasattr(Entry, 'BaseType'): + from lib.includes import t as _t + if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): + return ir.IntType(32) + if Entry.BaseType is _t.CEnum: + return ir.IntType(32) + if source_sha1: + ns_name = f"{source_sha1}.{clean_name}" + elif hasattr(self, '_struct_sha1_map') and clean_name in self._struct_sha1_map: + ns_name = f"{self._struct_sha1_map[clean_name]}.{clean_name}" + else: + ns_name = self._mangle_name(clean_name) + st = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed) + self.structs[clean_name] = st + # 尝试解析 typedef 的底层整数位宽 + width = self._resolve_typedef_int_width(clean_name) + if width is not None: + self.typedef_int_widths[clean_name] = width + return st + + def _resolve_typedef_int_width(self, name: str): + """解析 typedef 名称的底层整数位宽 + + 通过 CTypeRegistry 和 BuiltinTypeMap 动态解析, + 替代硬编码的 TYPEDEF_NAMES 映射表。 + 返回 int 位宽或 None(无法解析)。 + """ + from lib.includes.t import CTypeRegistry + from lib.core.Handles.HandlesBase import BuiltinTypeMap + + # 1. 先查 BuiltinTypeMap(覆盖 BYTEPTR 等指针别名) + bm = BuiltinTypeMap.Get(name) + if bm: + ctype_cls, ptr_count = bm + if ptr_count > 0: + return None # 指针类型,不是整数 typedef + llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 2. 再查 SymbolTable(用户定义的 typedef) + if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable: + Entry = self.SymbolTable[name] + if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: + if hasattr(Entry, 'BaseType') and Entry.BaseType: + from lib.includes import t as _t + if not isinstance(Entry.BaseType, (_t._CTypedef,)) and getattr(Entry, 'PtrCount', 0) == 0: + llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + if hasattr(Entry, 'OriginalType') and Entry.OriginalType: + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType: + if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and getattr(Entry.OriginalType, 'PtrCount', 0) == 0: + llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 3. 尝试 CTypeRegistry 直接按名称查找 + ctype_cls = CTypeRegistry.GetClassByName(name) + if ctype_cls: + llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 4. 特殊名称(非整数类型,但需要标记为 typedef 以跳过 opaque 定义) + _SPECIAL_TYPEDEFS = { + 'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', + 'CStruct', 'enum', 'REnum', 'renum', + 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', 'type', + } + if name in _SPECIAL_TYPEDEFS: + return 0 # 标记为 typedef,但位宽为 0(非整数) + + return None + + def _set_node_info(self, node, extra_info=""): + if hasattr(node, 'lineno'): + self._current_lineno = node.lineno + else: + self._current_lineno = 0 + if hasattr(node, 'col_offset'): + self._current_node_info = f"line {self._current_lineno}, col {node.col_offset}" + else: + self._current_node_info = f"line {self._current_lineno}" + if extra_info: + self._current_node_info += f" ({extra_info})" + + def _set_source_info(self, filepath): + self._current_source_file = filepath + try: + with open(filepath, 'r', encoding='utf-8') as f: + self._current_source_lines = f.readlines() + except Exception: # 文件读取失败时回退为空行列表 + self._current_source_lines = [] + + def _ns_hash(self): + if 'workspace' in self._ns_cache: + return self._ns_cache['workspace'] + cwd = os.getcwd().replace('\\', '/').lower() + digest = hashlib.sha1(cwd.encode('utf-8')).hexdigest()[:12] + self._ns_cache['workspace'] = digest + return digest + + def _skip_mangle(self, name): + skip_prefixes = ('llvm.', 'str_const_', 'printf', 'memset_pattern') + if any(name.startswith(p) for p in skip_prefixes): + return True + if '.' in name: + parts = name.split('.', 1) + if len(parts[0]) >= 8 and all(c in '0123456789abcdef' for c in parts[0]): + return True + return False + + def _mangle_name(self, name): + if self._skip_mangle(name): + return name + if name in self._export_funcs: + return name + if self.module_sha1: + return f"{self.module_sha1}.{name}" + return name + + def _find_function(self, name): + if name in self.functions: + return self.functions[name] + g = self.module.globals.get(name) + if g and isinstance(g, ir.Function): + self.functions[name] = g + return g + mangled = self._mangle_func_name(name) + if mangled != name: + if mangled in self.functions: + self.functions[name] = self.functions[mangled] + return self.functions[mangled] + g = self.module.globals.get(mangled) + if g and isinstance(g, ir.Function): + self.functions[mangled] = g + self.functions[name] = g + return g + for sha1 in self.ModuleSha1Map.values(): + prefixed = f"{sha1}.{name}" + if prefixed in self.functions: + self.functions[name] = self.functions[prefixed] + return self.functions[prefixed] + g = self.module.globals.get(prefixed) + if g and isinstance(g, ir.Function): + self.functions[prefixed] = g + self.functions[name] = g + return g + return None + + def _has_function(self, name): + return self._find_function(name) is not None + + def _get_or_declare_function(self, mangled_name, func_type): + for g in self.module.globals: + if isinstance(g, ir.Function) and g.name == mangled_name: + return g + return ir.Function(self.module, func_type, name=mangled_name) + + def _get_function(self, name): + func = self._find_function(name) + return func + + def _mangle_func_name(self, name, module_name=None): + if name in self._export_funcs: + return name + if name in self._export_extern_funcs and name not in self._current_module_func_names: + return name + # main 函数作为程序入口点,永远不混淆 + if name == 'main': + return name + # Try class_sha1_map first for class methods (e.g., 'md5.__init__' -> class 'md5') + class_sha1_map = getattr(self, 'class_sha1_map', {}) + if class_sha1_map: + if '.' in name: + base_class = name.split('.')[0] + if base_class in class_sha1_map: + sha1 = class_sha1_map[base_class] + return f"{sha1}.{name}" + elif name in class_sha1_map: + sha1 = class_sha1_map[name] + return f"{sha1}.{name}" + # If module_name is already a SHA1 hash (16 hex chars), use it directly + if module_name and len(module_name) == 16 and all(c in '0123456789abcdef' for c in module_name): + return f"{module_name}.{name}" + if module_name and module_name in self.ModuleSha1Map: + sha1 = self.ModuleSha1Map[module_name] + return f"{sha1}.{name}" + # Try parent package name (e.g., 'hashlib' -> 'hashlib.__init__') + if module_name: + init_name = f"{module_name}.__init__" + if init_name in self.ModuleSha1Map: + sha1 = self.ModuleSha1Map[init_name] + return f"{sha1}.{name}" + if self._skip_mangle(name): + return name + if self.module_sha1: + return f"{self.module_sha1}.{name}" + return name + + def _get_source_line(self, lineno): + if 0 < lineno <= len(self._current_source_lines): + return self._current_source_lines[lineno - 1].rstrip('\r\n') + return None + + def _get_node_info(self): + info = "" + if self._current_node_info: + info = f" [{self._current_node_info}]" + if self._current_source_file: + info += f" in {self._current_source_file}" + lineno = self._current_lineno + if lineno > 0: + info += f", line {lineno}:" + source_line = self._get_source_line(lineno) + if source_line: + info += f"\n → {source_line}" + return info diff --git a/lib/core/LLVMCG/ExprGen.py b/lib/core/LLVMCG/ExprGen.py new file mode 100644 index 0000000..78202d4 --- /dev/null +++ b/lib/core/LLVMCG/ExprGen.py @@ -0,0 +1,353 @@ +from __future__ import annotations +import llvmlite.ir as ir + + +class ExprGenMixin: + def emit_constant(self, value, type_name='int'): + if type_name == 'int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'uint64_t' or type_name == 'unsigned long long': + return ir.Constant(ir.IntType(64), int(value)) + elif type_name == 'uint32_t' or type_name == 'unsigned int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'uint16_t' or type_name == 'unsigned short': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'uint8_t' or type_name == 'unsigned char': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'int64_t' or type_name == 'long long': + return ir.Constant(ir.IntType(64), int(value)) + elif type_name == 'int32_t' or type_name == 'int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'int16_t' or type_name == 'short': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'int8_t' or type_name == 'char': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'float' or type_name == 'float32_t' or type_name == 'FLOAT32': + return ir.Constant(ir.FloatType(), float(value)) + elif type_name == 'double' or type_name == 'float64_t' or type_name == 'FLOAT64': + return ir.Constant(ir.DoubleType(), float(value)) + elif type_name == 'float16_t' or type_name == 'FLOAT16': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'float8_t' or type_name == 'FLOAT8': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'float128_t' or type_name == 'FLOAT128': + return ir.Constant(ir.IntType(128), int(value)) + elif type_name == 'string': + encoded = value.encode('utf-8') + b'\x00' + str_type = ir.ArrayType(ir.IntType(8), len(encoded)) + str_const = ir.Constant(str_type, bytearray(encoded)) + global_var = ir.GlobalVariable(self.module, str_type, name=f"str_const_{self.string_const_counter}") + self.string_const_counter += 1 + global_var.initializer = str_const + global_var.linkage = 'internal' + return self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8)), name="str") + return ir.Constant(ir.IntType(32), int(value)) + + def emit_binary_op(self, op, left, right, is_unsigned=False): + # 处理指针和整数之间的类型转换 + if isinstance(left.type, ir.PointerType) and isinstance(right.type, ir.IntType): + right = self.builder.zext(right, ir.IntType(64), name="int2ptrint") + if op == '+' or op == 'Add': + return self.builder.gep(left, [right], name="ptr_add") + elif op == '-' or op == 'Sub': + return self.builder.gep(left, [self.builder.neg(right, name="neg")], name="ptr_sub") + if isinstance(left.type, ir.IntType) and isinstance(right.type, ir.PointerType): + left = self.builder.zext(left, ir.IntType(64), name="int2ptrint2") + if op == '+' or op == 'Add': + return self.builder.gep(right, [left], name="ptr_add_rev") + is_float = isinstance(left.type, (ir.FloatType, ir.DoubleType)) or \ + isinstance(right.type, (ir.FloatType, ir.DoubleType)) + if is_float: + if isinstance(left.type, (ir.FloatType, ir.DoubleType)): + ftype = left.type + elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): + ftype = right.type + else: + ftype = ir.DoubleType() + if not isinstance(left.type, (ir.FloatType, ir.DoubleType)): + left = self._to_float(left, ftype) + elif left.type != ftype: + if isinstance(left.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + left = self.builder.fpext(left, ftype, name="fpext_l") + else: + left = self.builder.fptrunc(left, ftype, name="fptrunc_l") + if not isinstance(right.type, (ir.FloatType, ir.DoubleType)): + right = self._to_float(right, ftype) + elif right.type != ftype: + if isinstance(right.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + right = self.builder.fpext(right, ftype, name="fpext_r") + else: + right = self.builder.fptrunc(right, ftype, name="fptrunc_r") + float_ops = { + '+': self.builder.fadd, 'Add': self.builder.fadd, + '-': self.builder.fsub, 'Sub': self.builder.fsub, + '*': self.builder.fmul, 'Mult': self.builder.fmul, + '/': self.builder.fdiv, 'Div': self.builder.fdiv, + '%': self.builder.frem, 'Mod': self.builder.frem, + } + float_cmp_ops = { + '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', + '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', + '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', + } + if op in float_ops: + return float_ops[op](left, right, name=op) + if op in float_cmp_ops: + return self.builder.fcmp_ordered(float_cmp_ops[op], left, right, name=op) + if is_unsigned: + ops = { + '+': self.builder.add, 'Add': self.builder.add, + '-': self.builder.sub, 'Sub': self.builder.sub, + '*': self.builder.mul, 'Mult': self.builder.mul, + '/': self.builder.udiv, 'Div': self.builder.udiv, + '%': self.builder.urem, 'Mod': self.builder.urem, + '//': self.builder.udiv, 'FloorDiv': self.builder.udiv, + } + else: + ops = { + '+': self.builder.add, 'Add': self.builder.add, + '-': self.builder.sub, 'Sub': self.builder.sub, + '*': self.builder.mul, 'Mult': self.builder.mul, + '/': self.builder.sdiv, 'Div': self.builder.sdiv, + '%': self.builder.srem, 'Mod': self.builder.srem, + '//': self.builder.sdiv, 'FloorDiv': self.builder.sdiv, + } + cmp_ops = { + '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', + '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', + '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', + } + logic_ops = { + '&&': self.builder.and_, 'And': self.builder.and_, + '||': self.builder.or_, 'Or': self.builder.or_, + } + if op in ('>>', 'RShift') and not is_unsigned: + if isinstance(left.type, ir.IntType): + if left.type.width == 8: + is_unsigned = True + elif left.type.width == 16: + is_unsigned = True + elif left.type.width == 32: + if hasattr(self, '_last_var_name') and self._last_var_name: + is_unsigned = self._is_var_unsigned(self._last_var_name) + elif left.type.width == 64: + if hasattr(self, '_last_var_name') and self._last_var_name: + is_unsigned = self._is_var_unsigned(self._last_var_name) + shift_ops = { + '>>': self.builder.lshr if is_unsigned else self.builder.ashr, + 'RShift': self.builder.lshr if is_unsigned else self.builder.ashr, + '<<': self.builder.shl, 'LShift': self.builder.shl, + } + bit_ops = { + '&': self.builder.and_, + '|': self.builder.or_, + '^': self.builder.xor, + } + if op == '**' or op == 'Pow': + if isinstance(left, ir.Constant) and isinstance(right, ir.Constant): + try: + lv = left.constant + rv = right.constant + if isinstance(lv, int) and isinstance(rv, int) and rv >= 0: + result = lv ** rv + return ir.Constant(left.type, result) + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + import logging; logging.warning(f"异常被忽略: {_e}") + pass + if isinstance(left.type, (ir.FloatType, ir.DoubleType)): + ftype = left.type + elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): + ftype = right.type + else: + ftype = ir.DoubleType() + lf = self._to_float(left, ftype) + rf = self._to_float(right, ftype) + powf = self.module.globals.get('llvm.pow.f64') + if not powf: + fnty = ir.FunctionType(ir.DoubleType(), [ir.DoubleType(), ir.DoubleType()]) + powf = ir.Function(self.module, fnty, name='llvm.pow.f64') + if lf.type != ir.DoubleType(): + lf = self.builder.fpext(lf, ir.DoubleType(), name="ext_f64") + if rf.type != ir.DoubleType(): + rf = self.builder.fpext(rf, ir.DoubleType(), name="ext_f64") + result = self.builder.call(powf, [lf, rf], name="pow") + both_int = isinstance(left.type, ir.IntType) and isinstance(right.type, ir.IntType) + right_is_pos_int_const = isinstance(right, ir.Constant) and isinstance(right.constant, int) and right.constant >= 0 + if both_int and right_is_pos_int_const: + return self.builder.fptosi(result, left.type, name="pow2int") + if isinstance(left.type, ir.FloatType): + return self.builder.fptrunc(result, ir.FloatType(), name="pow2f32") + return result + if op in ops: + try: + return ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in shift_ops: + try: + return shift_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in bit_ops: + try: + return bit_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in cmp_ops: + try: + if is_unsigned: + return self.builder.icmp_unsigned(cmp_ops[op], left, right, name=op) + return self.builder.icmp_signed(cmp_ops[op], left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in logic_ops: + try: + return logic_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + return left + + def _to_float(self, val, ftype=None): + if ftype is None: + ftype = ir.DoubleType() + if isinstance(val.type, (ir.FloatType, ir.DoubleType)): + if val.type == ftype: + return val + if isinstance(val.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + return self.builder.fpext(val, ftype, name="fpext") + return self.builder.fptrunc(val, ftype, name="fptrunc") + if isinstance(val.type, ir.IntType): + if val.type.width == 1: + val = self.builder.zext(val, ir.IntType(32), name="bool2i32") + return self.builder.sitofp(val, ftype, name="int2float") + return val + + def emit_return(self, value=None): + if not self.builder or self.builder.block.is_terminated: + return + if value is not None: + self._unregister_local_heap_ptr(value) + self._emit_local_heap_frees() + if hasattr(self, '_variadic_info') and self._variadic_info and self._variadic_info.get('va_start_called'): + va_list_ptr = self._variadic_info['va_list_ptr'] + self.emit_va_end(va_list_ptr) + if value is None: + if self.func and hasattr(self.func, 'ftype'): + ret_type = self.func.ftype.return_type + if isinstance(ret_type, ir.IntType): + self.builder.ret(ir.Constant(ret_type, 0)) + elif isinstance(ret_type, ir.PointerType): + self.builder.ret(ir.Constant(ret_type, None)) + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): + self.builder.ret(ir.Constant(ret_type, 0.0)) + elif isinstance(ret_type, ir.IdentifiedStructType): + if ret_type.elements: + zero_val = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + self.builder.ret(zero_val) + elif isinstance(ret_type, ir.ArrayType): + self.builder.ret(ir.Constant(ret_type, None)) + else: + self.builder.ret_void() + else: + self.builder.ret_void() + else: + if self.func and hasattr(self.func, 'ftype'): + ret_type = self.func.ftype.return_type + if ret_type != value.type: + if isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.PointerType): + if value.type.pointee == ret_type: + value = self._load(value, name="ret_Load") + else: + value = self.builder.bitcast(value, ret_type, name="ret_cast") + elif isinstance(value.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): + if isinstance(value.type.pointee, ir.IntType) and isinstance(ret_type, ir.IntType) and value.type.pointee.width == ret_type.width: + value = self._load(value, name="ret_Load") + elif isinstance(ret_type, ir.IntType): + value = self.builder.ptrtoint(value, ret_type, name="ret_ptrtoint") + elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType): + value = self._load(value, name="ret_Load") + elif isinstance(value.type.pointee, ir.PointerType): + Loaded = self._load(value, name="ret_deref") + if Loaded.type == ret_type: + value = Loaded + elif isinstance(ret_type, ir.IntType): + value = self.builder.ptrtoint(Loaded, ret_type, name="ret_ptrtoint") + elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType): + if value.type.width < ret_type.width: + # 有符号值用 sext,无符号值用 zext + is_unsigned = id(value) in self._unsigned_results + if is_unsigned: + value = self.builder.zext(value, ret_type, name="ret_zext") + else: + value = self.builder.sext(value, ret_type, name="ret_sext") + elif value.type.width > ret_type.width: + value = self.builder.trunc(value, ret_type, name="ret_trunc") + elif isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.IntType): + value = self.builder.inttoptr(value, ret_type, name="ret_inttoptr") + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, ir.IntType): + value = self.builder.sitofp(value, ret_type, name="ret_int2float") + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, (ir.FloatType, ir.DoubleType)): + if ret_type != value.type: + value = self.builder.fpext(value, ret_type, name="ret_fpext") + self.builder.ret(value) + + def _emit_printf(self, args, unsigned_flags=None, sep=" ", end="\n"): + if not args: + return None + if unsigned_flags is None: + unsigned_flags = [] + format_str = "" + cast_args = [] + for i, arg in enumerate(args): + is_u = i < len(unsigned_flags) and unsigned_flags[i] + if isinstance(arg.type, ir.IntType): + if arg.type.width == 8: + format_str += "%c" + ext = self.builder.zext(arg, ir.IntType(32), name="char2int") + cast_args.append(ext) + elif arg.type.width == 64: + format_str += "%llu" if is_u else "%lld" + cast_args.append(arg) + else: + format_str += "%u" if is_u else "%d" + cast_args.append(arg) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(arg) + elif isinstance(arg.type, ir.PointerType): + if isinstance(arg.type.pointee, ir.IntType) and arg.type.pointee.width == 8: + format_str += "%s" + cast_args.append(arg) + else: + format_str += "%d" + int_val = self.builder.ptrtoint(arg, ir.IntType(64), name="ptr2int") + trunc_val = self.builder.trunc(int_val, ir.IntType(32), name="trunc") + cast_args.append(trunc_val) + else: + format_str += "%d" + cast_args.append(arg) + if sep is not None and i < len(args) - 1: + format_str += sep + if end is not None: + format_str += end + string_type = ir.ArrayType(ir.IntType(8), len(format_str.encode('utf-8')) + 1) + string_const = ir.Constant(string_type, bytearray(format_str + '\x00', 'utf-8')) + global_var = ir.GlobalVariable(self.module, string_type, name=f"str_const_{self.string_const_counter}") + self.string_const_counter += 1 + global_var.initializer = string_const + global_var.linkage = 'internal' + format_ptr = self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) + call_args = [format_ptr] + cast_args + printf_func = self.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) + return self.builder.call(printf_func, call_args, name="call_printf") + + def emit_sizeof(self, type_name): + for class_name, struct_type in self.structs.items(): + if type_name == class_name: + size = self._get_struct_size(struct_type) + if size > 0: + return ir.Constant(ir.IntType(64), size) + return ir.Constant(ir.IntType(64), 4) diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py new file mode 100644 index 0000000..faadbf2 --- /dev/null +++ b/lib/core/LLVMCG/FuncGen.py @@ -0,0 +1,386 @@ +from __future__ import annotations +import ast +import os +import llvmlite.ir as ir + + +class FuncGenMixin: + + def setup_from_symbol_table(self, SymbolTable): + self.SymbolTable = SymbolTable + for name, info in SymbolTable.items(): + if not isinstance(info, dict): + if hasattr(info, 'get'): + info = dict(info) if hasattr(info, '__iter__') else {} + else: + continue + TypeKind = info.get('type', '') + if TypeKind == 'struct': + ClassName = name + self.class_methods[ClassName] = [] + self.class_members[ClassName] = [] + members = info.get('members', {}) + if members: + for MemberName, MemberInfo in members.items(): + if isinstance(MemberInfo, dict): + MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False)) + self.class_members[ClassName].append((MemberName, MemberType)) + elif isinstance(MemberInfo, _CTypeInfo): + MemberType = self._ctype_to_llvm(MemberInfo) + if MemberType is None: + MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr) + self.class_members[ClassName].append((MemberName, MemberType)) + self._generate_structs() + self._create_Vtable_globals() + + def register_method(self, ClassName, MethodName): + if ClassName not in self.class_methods: + self.class_methods[ClassName] = [] + if ClassName not in self.class_members: + self.class_members[ClassName] = [] + self._generate_structs() + self._create_Vtable_globals() + if MethodName not in self.class_methods[ClassName]: + self.class_methods[ClassName].append(MethodName) + + def _adjust_args(self, args, func): + adjusted = [] + for i, (arg, param) in enumerate(zip(args, func.args)): + if arg.type != param.type: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + continue + try: + if isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): + if isinstance(param.type.pointee, ir.IntType) and param.type.pointee.width == 8 and arg.type.width == 8: + # 当参数是 i8(字符值)而函数期望 i8*(字符串指针)时 + # 为字符值分配内存,创建 null-terminated 字符串 + tmp = self._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"char2str_arg_{i}") + zero = ir.Constant(ir.IntType(32), 0) + char_ptr = self.builder.gep(tmp, [zero, zero], name=f"char2str_ptr_{i}") + self._store(arg, char_ptr) + null_ptr = self.builder.gep(tmp, [zero, ir.Constant(ir.IntType(32), 1)], name=f"char2str_null_{i}") + self._store(ir.Constant(ir.IntType(8), 0), null_ptr) + adjusted.append(char_ptr) + else: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 当参数是指针而函数期望整数时,使用 ptrtoint + adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) + else: + if arg.type.width < 32: + arg = self.builder.zext(arg, ir.IntType(32), name=f"zext_arg_{i}") + adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 当参数是指针而函数期望整数时,使用 ptrtoint + adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.PointerType): + if isinstance(arg.type.pointee, ir.PointerType) and isinstance(param.type.pointee, ir.IntType): + Loaded = self._load(arg, name=f"Load_arg_{i}") + adjusted.append(Loaded) + elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): + zero = ir.Constant(ir.IntType(32), 0) + elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") + if elem_ptr.type != param.type: + adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) + else: + adjusted.append(elem_ptr) + elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, ir.PointerType): + zero = ir.Constant(ir.IntType(32), 0) + elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") + if elem_ptr.type != param.type: + adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) + else: + adjusted.append(elem_ptr) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + else: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(arg.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + tmp = self._alloca(param.type, name=f"temp_arg_{i}") + Loaded = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") + Loaded_val = self._load(Loaded, name=f"Load_arg_{i}") + self._store(Loaded_val, tmp) + adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) + else: + tmp = self._alloca(param.type, name=f"temp_arg_{i}") + cast_ptr = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") + Loaded_val = self._load(cast_ptr, name=f"Load_arg_{i}") + self._store(Loaded_val, tmp) + adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: + tmp = self._alloca(arg.type, name=f"temp_arg_{i}") + self._store(arg, tmp) + adjusted.append(tmp) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.IntType): + if arg.type.width < param.type.width: + # 整数扩展:使用 sext(符号扩展)以正确处理负数 + adjusted.append(self.builder.sext(arg, param.type, name=f"sext_arg_{i}")) + else: + adjusted.append(self.builder.trunc(arg, param.type, name=f"trunc_arg_{i}")) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): + if isinstance(arg.type, ir.DoubleType) and isinstance(param.type, ir.FloatType): + adjusted.append(self.builder.fptrunc(arg, param.type, name=f"fptrunc_arg_{i}")) + elif isinstance(arg.type, ir.FloatType) and isinstance(param.type, ir.DoubleType): + adjusted.append(self.builder.fpext(arg, param.type, name=f"fpext_arg_{i}")) + else: + adjusted.append(arg) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, ir.IntType): + adjusted.append(self.builder.fptosi(arg, param.type, name=f"fptosi_arg_{i}")) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): + adjusted.append(self.builder.sitofp(arg, param.type, name=f"sitofp_arg_{i}")) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): + # 整数转指针:inttoptr + if arg.type.width < 64: + i64_val = self.builder.sext(arg, ir.IntType(64), name=f"sext_arg_{i}") + adjusted.append(self.builder.inttoptr(i64_val, param.type, name=f"inttoptr_arg_{i}")) + else: + adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 指针转整数:ptrtoint + i64_val = self.builder.ptrtoint(arg, ir.IntType(64), name=f"ptrtoint_arg_{i}") + if i64_val.type.width > param.type.width: + adjusted.append(self.builder.trunc(i64_val, param.type, name=f"trunc_arg_{i}")) + elif i64_val.type.width < param.type.width: + adjusted.append(self.builder.sext(i64_val, param.type, name=f"sext_arg_{i}")) + else: + adjusted.append(i64_val) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + except Exception: # 参数类型调整失败时使用简化回退逻辑 + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: + tmp = self._alloca(arg.type, name=f"temp_arg_{i}") + self._store(arg, tmp) + adjusted.append(tmp) + else: + adjusted.append(arg) + else: + adjusted.append(arg) + while len(adjusted) < len(func.args): + missing_idx = len(adjusted) + param = func.args[missing_idx] + param_type = param.type if hasattr(param, 'type') else param + if isinstance(param_type, ir.PointerType): + adjusted.append(ir.Constant(param_type, None)) + elif isinstance(param_type, ir.IntType): + adjusted.append(ir.Constant(param_type, 0)) + elif isinstance(param_type, (ir.FloatType, ir.DoubleType)): + adjusted.append(ir.Constant(param_type, 0.0)) + else: + adjusted.append(ir.Constant(ir.IntType(32), 0)) + if func.type.pointee.var_arg: + for i in range(len(func.args), len(args)): + arg = args[i] + adjusted.append(arg) + return adjusted + + def _get_member_offset(self, field_name, ClassName=None): + has_vtable = ClassName and (ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes) + base = 1 if has_vtable else 0 + if ClassName and ClassName in self.structs: + struct_type = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: + if ClassName in self.class_members: + expected_fields = len(self.class_members[ClassName]) + actual_elements = len(struct_type.elements) + if base > 0 and actual_elements == expected_fields: + base = 0 + if ClassName and ClassName in self.class_members: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + short_name = ClassName.split('.')[-1] if ClassName and '.' in ClassName else None + if short_name and short_name in self.class_members: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + if ClassName and field_name: + if ClassName not in self.class_members or field_name not in [n for n, _ in self.class_members.get(ClassName, [])]: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): + sha1_map = getattr(self, 'ModuleSha1Map', {}) + for mod_name, mod_sha1 in sha1_map.items(): + stub_name = f"{mod_sha1}.stub.ll" + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, stub_name, self) + if ClassName in self.class_members and len(self.class_members[ClassName]) > 0: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + break + if short_name: + for mod_name, mod_sha1 in sha1_map.items(): + stub_name = f"{mod_sha1}.stub.ll" + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_name, stub_name, self) + if short_name in self.class_members and len(self.class_members[short_name]) > 0: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + break + if ClassName and field_name: + for cn_key in self.class_members: + if cn_key == ClassName or cn_key.endswith(f'.{ClassName}') or (short_name and (cn_key == short_name or cn_key.endswith(f'.{short_name}'))): + for i, (name, _) in enumerate(self.class_members[cn_key]): + if name == field_name: + return base + i + if ClassName and ClassName in self.structs: + struct_type = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: + for cn_key, members in self.class_members.items(): + if cn_key == short_name or (short_name and cn_key.endswith(f'.{short_name}')): + for i, (name, _) in enumerate(members): + if name == field_name and i < len(struct_type.elements): + return i + break + else: + if short_name: + for cn_key, members in self.class_members.items(): + sn = cn_key.split('.')[-1] if '.' in cn_key else cn_key + if sn == short_name: + for i, (name, _) in enumerate(members): + if name == field_name and i < len(struct_type.elements): + return i + break + if ClassName and field_name and ClassName not in self.class_members: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): + for temp_dir_candidate in [getattr(self, '_temp_dir', None)]: + if temp_dir_candidate and os.path.isdir(temp_dir_candidate): + for pyi_file in os.listdir(temp_dir_candidate): + if pyi_file.endswith('.pyi'): + stub_name = pyi_file.replace('.pyi', '.stub.ll') + short_cn = short_name if short_name else ClassName + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_cn, stub_name, self) + if short_cn in self.class_members and len(self.class_members[short_cn]) > 0: + for i, (name, _) in enumerate(self.class_members[short_cn]): + if name == field_name: + return base + i + break + if ClassName and ClassName in self.structs and (ClassName not in self.class_members or len(self.class_members.get(ClassName, [])) == 0): + struct_type = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ClassHandler'): + class_handler = self._Trans.ClassHandler + if hasattr(self, '_current_tree') and self._current_tree: + for node in ast.iter_child_nodes(self._current_tree): + if isinstance(node, ast.ClassDef) and (node.name == ClassName or node.name == short_name): + if node.name not in self.class_members: + self.class_members[node.name] = [] + if len(self.class_members[node.name]) == 0: + class_handler._PreRegisterClassMembers(node, self) + if ClassName in self.class_members: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + if short_name and short_name in self.class_members: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + break + return None + + def _resolve_class_for_var(self, var_name): + for ClassName in self.class_methods: + if var_name == ClassName or var_name.startswith(f"__with_{ClassName}_"): + return ClassName + if var_name in self.variables: + var = self.variables[var_name] + if isinstance(var.type, ir.PointerType): + for ClassName, struct_type in self.structs.items(): + if var.type.pointee == struct_type: + return ClassName + if isinstance(var.type.pointee, ir.PointerType) and var.type.pointee.pointee == struct_type: + return ClassName + return None + + def _GetOrCreateFunc(self, FuncName, ArgTypes): + mangled_name = self._mangle_func_name(FuncName) + if mangled_name in self.functions: + return self.functions[mangled_name] + FuncType = self._InferFuncTypeForCall(FuncName, ArgTypes) + try: + func = ir.Function(self.module, FuncType, name=mangled_name) + except Exception: # 函数名冲突时添加前缀重试 + func = ir.Function(self.module, FuncType, name=f"_{mangled_name}") + self.functions[mangled_name] = func + return func + + def _resolve_method_class(self, MethodName): + for ClassName, methods in self.class_methods.items(): + if MethodName in methods: + return ClassName + full_name = f"{ClassName}.{MethodName}" + if full_name in methods: + return ClassName + return None + + def _infer_return_type(self, FuncName): + if FuncName in self.functions: + return self.functions[FuncName].type.pointee.return_type + if FuncName in self.known_return_types: + return self.known_return_types[FuncName] + for ClassName, methods in self.class_methods.items(): + for method in methods: + if FuncName == method: + return ir.VoidType() + return ir.IntType(32) + + def _InferFuncTypeForCall(self, FuncName, ArgTypes): + return_type = self._infer_return_type(FuncName) + if not ArgTypes: + for ClassName, methods in self.class_methods.items(): + if FuncName in methods: + if ClassName in self.structs: + ArgTypes = [ir.PointerType(self.structs[ClassName])] + else: + ArgTypes = [ir.PointerType(ir.LiteralStructType([ir.PointerType(ir.IntType(8)), ir.IntType(32)]))] + break + else: + ArgTypes = [ir.IntType(32)] + return ir.FunctionType(return_type, ArgTypes) + + def _get_or_declare_func(self, name, func_type): + import re + for fname, fobj in self.functions.items(): + if fname == name: + return fobj + if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): + return fobj + func_decl = ir.Function(self.module, func_type, name=name) + self.functions[name] = func_decl + return func_decl + + def get_or_declare_c_func(self, name, fallback_type=None): + if name in self.functions: + return self.functions[name] + import re + for fname, fobj in self.functions.items(): + if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): + return fobj + stub_func_type = None + if hasattr(self, '_import_handler_ref') and self._import_handler_ref: + try: + stub_func_type = self._import_handler_ref._LookupStubFuncType(name, self) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"查找桩函数类型失败: {_e}", "Exception") + if stub_func_type: + func_decl = ir.Function(self.module, stub_func_type, name=name) + self.functions[name] = func_decl + return func_decl + if fallback_type is not None: + func_decl = ir.Function(self.module, fallback_type, name=name) + self.functions[name] = func_decl + return func_decl + return None diff --git a/lib/core/LLVMCG/MemoryOps.py b/lib/core/LLVMCG/MemoryOps.py new file mode 100644 index 0000000..7945429 --- /dev/null +++ b/lib/core/LLVMCG/MemoryOps.py @@ -0,0 +1,312 @@ +from __future__ import annotations +import llvmlite.ir as ir + + +class MemoryOpsMixin: + + def _register_local_heap_ptr(self, val, ClassName=None, VarName=None): + if isinstance(val.type, ir.PointerType): + pointee = val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + self._local_heap_ptrs.append((val, 'struct', ClassName)) + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + self._local_heap_ptrs.append((val, 'i8', ClassName)) + if VarName: + self._var_to_heap_ptr[VarName] = val + + def _unregister_local_heap_ptr(self, val): + self._local_heap_ptrs = [(v, t, cn) for v, t, cn in self._local_heap_ptrs if v is not val] + + def _emit_local_heap_frees(self): + if not self._local_heap_ptrs or not self.builder: + return + # 创建一个集合来跟踪已经删除的对象 + deleted_objects = set() + for ptr, ptr_type, ClassName in self._local_heap_ptrs: + # 先检查指针是否为 null + if ptr_type == 'i8': + # 对于 i8* 类型的指针,加载其值并检查是否为 null + Loaded_ptr = self.builder.load(ptr, name="load_ptr") + null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) + is_null = self.builder.icmp_unsigned('==', Loaded_ptr, null_ptr, name="is_null") + # 创建一个基本块来处理非 null 的情况 + not_null_block = self.builder.append_basic_block(name="not_null") + # 创建一个基本块来处理下一个对象 + next_block = self.builder.append_basic_block(name="next") + # 如果指针为 null,跳转到下一个对象 + self.builder.cbranch(is_null, next_block, not_null_block) + # 切换到非 null 的基本块 + self.builder.position_at_end(not_null_block) + # 然后调用 __del__ 方法 + if ClassName and self._has_function(f'{ClassName}.__del__'): + if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: + cast_ptr = self.builder.bitcast(ptr, ir.PointerType(self.structs[ClassName]), name=f"cast_{ClassName}") + else: + cast_ptr = ptr + if cast_ptr not in deleted_objects: + self.builder.call(self._get_function(f'{ClassName}.__del__'), [cast_ptr], name=f"call_{ClassName}.__del__") + deleted_objects.add(cast_ptr) + # 最后释放内存 + if ptr_type == 'struct': + raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="local_free_cast") + elif ptr_type == 'i8': + raw = ptr + else: + continue + free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) + free_func = self._get_or_declare_func('free', free_type) + self.builder.call(free_func, [raw]) + # 如果是 i8* 类型的指针,跳转到下一个对象 + if ptr_type == 'i8': + self.builder.branch(next_block) + # 切换到下一个对象的基本块 + self.builder.position_at_end(next_block) + self._local_heap_ptrs = [] + + def _RegisterTempPtr(self, val): + if isinstance(val.type, ir.PointerType): + pointee = val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + for CN, ST in self.structs.items(): + if pointee == ST: + self._temp_struct_ptrs.append(val) + return + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + self._temp_struct_ptrs.append(val) + + def _UnregisterTempPtr(self, val): + self._temp_struct_ptrs = [t for t in self._temp_struct_ptrs if t is not val] + + def _EmitTempFrees(self): + if not self._temp_struct_ptrs or not self.builder: + return + for ptr in self._temp_struct_ptrs: + if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="free_cast") + elif isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: + raw = ptr + else: + continue + free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) + free_func = self._get_or_declare_func('free', free_type) + self.builder.call(free_func, [raw]) + self._temp_struct_ptrs = [] + + def _ZeroConst(self, typ): + if isinstance(typ, ir.PointerType): + return ir.Constant(typ, None) + return ir.Constant(typ, 0) + + def _alloca(self, typ, name='', align=None, size=None): + if align is None: + align = self._get_align(typ) + if size is not None: + instr = self.builder.alloca(typ, size=size, name=name) + else: + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + return instr + + def _allocaEntry(self, typ, name='', align=None): + if align is None: + align = self._get_align(typ) + saved_block = self.builder.block + entry_block = self.func.entry_basic_block + if entry_block.instructions: + first_instr = entry_block.instructions[0] + self.builder.position_before(first_instr) + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + self.builder.position_at_end(saved_block) + else: + self.builder.position_at_start(entry_block) + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + self.builder.position_at_end(saved_block) + return instr + + def _load(self, ptr, name='', align=None): + if align is None: + if isinstance(ptr.type, ir.PointerType): + align = self._get_align(ptr.type.pointee) + else: + align = 0 + if isinstance(ptr.type, ir.PointerType): + pointee_type = ptr.type.pointee + if isinstance(pointee_type, ir.IdentifiedStructType) and pointee_type.name in self.typedef_int_widths: + width = self.typedef_int_widths[pointee_type.name] + if width > 0: + actual_type = ir.IntType(width) + bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast_Load") + return self.builder.load(bitcast_ptr, name=name, align=align) + return self.builder.load(ptr, name=name, align=align) + + def _Load_var(self, name): + if name in self._direct_values: + return self._direct_values[name] + if name in self.variables and self.variables[name] is not None: + VarPtr = self.variables[name] + if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return VarPtr + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return VarPtr + return self._load(VarPtr, name=name) + if name in self.global_vars and name in self.module.globals: + GVar = self.module.globals[name] + self.variables[name] = 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 self._load(GVar, name=name) + if name in self.module.globals: + GVar = self.module.globals[name] + self.variables[name] = 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 self._load(GVar, name=name) + return None + + def _store_var(self, name, value): + if name in self._direct_values: + old_val = self._direct_values.pop(name) + if name not in self.variables or self.variables[name] is None: + var = self.builder.alloca(old_val.type, name=name) + self._store(old_val, var) + self.variables[name] = var + if name in self.variables and self.variables[name] is not None: + self._store(value, self.variables[name]) + else: + var = self.builder.alloca(value.type, name=name) + self._store(value, var) + self.variables[name] = var + + def _ensure_alloca(self, name, llvm_type): + if name in self._direct_values: + val = self._direct_values.pop(name) + var = self.builder.alloca(llvm_type, name=name) + self._store(val, var) + self.variables[name] = var + return var + if name in self.variables and self.variables[name] is not None: + return self.variables[name] + var = self.builder.alloca(llvm_type, name=name) + self.variables[name] = var + return var + + def _coerce_value(self, val, target_type): + if val.type == target_type: + return val + if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: + if isinstance(val.type, ir.IntType): + return val + if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.IntType): + if target_type.width < val.type.width: + return self.builder.trunc(val, target_type, name="trunc_store") + else: + # 使用 sext(符号扩展)以正确处理负数 + return self.builder.sext(val, target_type, name="sext_store") + if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.PointerType): + if isinstance(val, ir.Constant) and val.constant is None: + return ir.Constant(target_type, None) + return self.builder.bitcast(val, target_type, name="ptr_bitcast_store") + if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.IntType): + if val.type.width < 64: + val = self.builder.zext(val, ir.IntType(64), name="zext_ptr_store") + return self.builder.inttoptr(val, target_type, name="int_to_ptr_store") + if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.PointerType): + if isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == target_type.width: + return self.builder.load(val, name="load_ptr_as_int_store") + if target_type.width <= 8 and isinstance(val.type.pointee, ir.IntType): + Loaded = self.builder.load(val, name="load_ptr_byte_store") + if Loaded.type != target_type: + if isinstance(Loaded.type, ir.IntType) and isinstance(target_type, ir.IntType): + if target_type.width < Loaded.type.width: + return self.builder.trunc(Loaded, target_type, name="trunc_ptr_byte_store") + return self.builder.zext(Loaded, target_type, name="zext_ptr_byte_store") + return Loaded + return self.builder.ptrtoint(val, target_type, name="ptr_to_int_store") + if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType): + return self.builder.fptrunc(val, target_type, name="fptrunc_store") + if isinstance(target_type, ir.DoubleType) and isinstance(val.type, ir.FloatType): + return self.builder.fpext(val, target_type, name="fpext_store") + if isinstance(target_type, ir.IntType) and isinstance(val.type, (ir.FloatType, ir.DoubleType)): + return self.builder.fptosi(val, target_type, name="fptosi_store") + if isinstance(target_type, (ir.FloatType, ir.DoubleType)) and isinstance(val.type, ir.IntType): + return self.builder.sitofp(val, target_type, name="sitofp_store") + if isinstance(target_type, ir.ArrayType) and isinstance(val.type, ir.ArrayType): + if target_type.count == val.type.count and target_type.element == val.type.element: + return val + if (isinstance(target_type.element, ir.IntType) and target_type.element.width == 8 + and isinstance(val.type.element, ir.IntType) and val.type.element.width == 8): + if target_type.count > val.type.count: + padded = list(val.constant) if hasattr(val, 'constant') else [] + if padded and len(padded) == val.type.count: + padded.extend([ir.Constant(ir.IntType(8), 0)] * (target_type.count - val.type.count)) + return ir.Constant(target_type, padded) + elif target_type.count < val.type.count: + trimmed = list(val.constant) if hasattr(val, 'constant') else [] + if trimmed and len(trimmed) == val.type.count: + return ir.Constant(target_type, trimmed[:target_type.count]) + if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType): + if val.type.pointee == target_type: + return self.builder.load(val, name="Load_struct_for_store") + if isinstance(val.type.pointee, ir.IdentifiedStructType) and isinstance(target_type, ir.IdentifiedStructType): + if val.type.pointee.name == target_type.name: + Loaded = self.builder.load(val, name="Load_struct_for_store") + if Loaded.type == target_type: + return Loaded + return None + + def _store(self, val, ptr, align=None): + if align is None: + if isinstance(ptr.type, ir.PointerType): + align = self._get_align(ptr.type.pointee) + else: + align = 0 + if isinstance(ptr.type, ir.PointerType): + target_type = ptr.type.pointee + if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: + if isinstance(val.type, ir.IntType): + width = self.typedef_int_widths[target_type.name] + if width > 0: + actual_type = ir.IntType(width) + bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast") + if val.type.width != actual_type.width: + if val.type.width > actual_type.width: + val = self.builder.trunc(val, actual_type, name="trunc_typedef") + else: + val = self.builder.zext(val, actual_type, name="zext_typedef") + return self.builder.store(val, bitcast_ptr, align=align) + if val.type != target_type: + if isinstance(val, ir.Constant) and val.constant is None: + if isinstance(target_type, ir.PointerType): + val = ir.Constant(target_type, None) + elif isinstance(target_type, ir.IdentifiedStructType): + val = ir.Constant(ir.PointerType(target_type), None) + ptr = self.builder.bitcast(ptr, ir.PointerType(ir.PointerType(target_type)), name="null_struct_ptr_cast") + else: + coerced = self._coerce_value(val, target_type) + if coerced is not None: + val = coerced + else: + src_info = self._get_node_info() + raise TypeError(f"cannot store {val.type} to {ptr.type}: mismatching types{src_info}") + return self.builder.store(val, ptr, align=align) + + def _get_var_ptr(self, name): + if name in self._reg_values: + val = self._reg_values[name] + var = self._alloca(val.type, name=name) + self._store(val, var) + self.variables[name] = var + del self._reg_values[name] + return var + if name in self.variables and self.variables[name] is not None: + return self.variables[name] + return None diff --git a/lib/core/LLVMCG/StructGen.py b/lib/core/LLVMCG/StructGen.py new file mode 100644 index 0000000..2c0f089 --- /dev/null +++ b/lib/core/LLVMCG/StructGen.py @@ -0,0 +1,463 @@ +from __future__ import annotations +import re +import ast +import llvmlite.ir as ir +from llvmlite.ir.values import _Undefined + + +class StructGenMixin: + + def _get_align(self, llvm_type): + if isinstance(llvm_type, ir.IntType): + return max(1, llvm_type.width // 8) + if isinstance(llvm_type, ir.FloatType): + return 4 + if isinstance(llvm_type, ir.DoubleType): + return 8 + if isinstance(llvm_type, ir.PointerType): + return self.ptr_size + if isinstance(llvm_type, ir.ArrayType): + return self._get_align(llvm_type.element) + if isinstance(llvm_type, ir.LiteralStructType): + return max((self._get_align(f) for f in llvm_type.elements), default=1) + if isinstance(llvm_type, ir.IdentifiedStructType): + if llvm_type.elements is None or len(llvm_type.elements) == 0: + return self.ptr_size # opaque struct, assume pointer alignment + return max((self._get_align(f) for f in llvm_type.elements), default=1) + if isinstance(llvm_type, ir.VoidType): + return 0 + return 4 + + def _get_struct_size(self, llvm_type): + if isinstance(llvm_type, ir.IntType): + return max(1, llvm_type.width // 8) + if isinstance(llvm_type, ir.FloatType): + return 4 + if isinstance(llvm_type, ir.DoubleType): + return 8 + if isinstance(llvm_type, ir.PointerType): + return self.ptr_size + if isinstance(llvm_type, ir.ArrayType): + return self._get_struct_size(llvm_type.element) * llvm_type.count + if isinstance(llvm_type, ir.LiteralStructType): + total = 0 + max_align = 1 + for f in llvm_type.fields: + fa = self._get_align(f) + fs = self._get_struct_size(f) + max_align = max(max_align, fa) + if fa > 1: + total = (total + fa - 1) // fa * fa + total += fs + if max_align > 1: + total = (total + max_align - 1) // max_align * max_align + return total + if isinstance(llvm_type, ir.IdentifiedStructType): + if llvm_type.elements is None or len(llvm_type.elements) == 0: + return self.ptr_size # opaque struct, assume pointer size + total = 0 + max_align = 1 + for f in llvm_type.elements: + fa = self._get_align(f) + fs = self._get_struct_size(f) + max_align = max(max_align, fa) + if fa > 1: + total = (total + fa - 1) // fa * fa + total += fs + if max_align > 1: + total = (total + max_align - 1) // max_align * max_align + return total + return 4 + + @staticmethod + def _strip_unnecessary_quotes(ir_str): + def _unquote(m): + prefix = m.group(1) + name = m.group(2) + if '.' in name: + return m.group(0) + if re.match(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$', name): + return prefix + name + return m.group(0) + return re.sub(r'([@%])"([^"]+)"', _unquote, ir_str) + + def finalize(self): + self._set_Vtable_initializers() + self._fix_global_var_init() + try: + ir_text = str(self.module) + except TypeError as e: + for func in self.module.functions: + for block in func.blocks: + for instr in block.instructions: + try: + str(instr) + except TypeError as te: + pass + raise + ir_text = self._strip_unnecessary_quotes(ir_text) + struct_defs = [] + struct_names = set() + for ClassName, struct_type in self.structs.items(): + if isinstance(struct_type, ir.IdentifiedStructType): + sname = struct_type.name + if sname[0].isdigit() or '.' in sname or not sname.replace('_', '').replace('.', '').isalnum(): + sname_ir = f'%"{sname}"' + else: + sname_ir = f'%{sname}' + if struct_type.elements is None or len(struct_type.elements) == 0: + if ClassName not in self.typedef_int_widths: + struct_names.add(sname) + struct_defs.append(f'{sname_ir} = type opaque') + continue + elems = ', '.join(str(e) for e in struct_type.elements) + if struct_type.packed: + struct_defs.append(f'{sname_ir} = type <{{ {elems} }}>') + else: + struct_defs.append(f'{sname_ir} = type {{ {elems} }}') + struct_names.add(sname) + if struct_defs: + lines = ir_text.split('\n') + filtered = [] + for line in lines: + stripped = line.strip() + skip = False + for name in struct_names: + if name[0].isdigit() or '.' in name or not name.replace('_', '').replace('.', '').isalnum(): + patterns = [f'%"{name}" = type', f'%"{name}"=type', f'%{name} = type', f'%{name}=type'] + else: + patterns = [f'%{name} = type', f'%{name}= type', f'%{name}=type'] + for p in patterns: + if stripped.startswith(p): + skip = True + break + if skip: + break + if not skip: + filtered.append(line) + ir_text = '\n'.join(filtered) + header_end = ir_text.find('\ndefine') + if header_end == -1: + header_end = ir_text.find('\ndeclare') + if header_end == -1: + header_end = ir_text.find('\n@') + if header_end == -1: + header_end = len(ir_text) + insert_pos = ir_text.rfind('\n', 0, header_end) + if insert_pos == -1: + insert_pos = header_end + struct_block = '\n'.join(struct_defs) + '\n' + ir_text = ir_text[:insert_pos + 1] + struct_block + ir_text[insert_pos + 1:] + for name in struct_names: + if name[0].isdigit() or '.' in name: + ir_text = re.sub( + r'%' + re.escape(name) + r'(?=[^a-zA-Z0-9_$\.]|$)', + r'%"' + name + r'"', + ir_text + ) + + return ir_text + + def _collect_classes_and_methods(self, ast_nodes, parent=None): + current_class = None + for node in ast_nodes: + if isinstance(node, str): + continue + node.parent = parent + node_type = type(node).__name__ + if node_type == 'Struct': + if hasattr(node, 'name'): + current_class = node.name + self.class_methods[current_class] = [] + self.class_members[current_class] = [] + if hasattr(node, 'decls') and node.decls: + for decl in node.decls: + if type(decl).__name__ == 'Decl' and hasattr(decl, 'name'): + member_type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32) + self.class_members[current_class].append((decl.name, member_type)) + elif node_type == 'FuncDef': + if current_class and current_class in self.class_methods: + MethodName = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method' + if not MethodName.startswith(f"{current_class}."): + MethodName = f"{current_class}.{MethodName}" + self.class_methods[current_class].append(MethodName) + if hasattr(node, 'body') and isinstance(node.body, list): + self._collect_classes_and_methods(node.body, parent=node) + elif hasattr(node, 'BlockItems') and node.BlockItems: + self._collect_classes_and_methods(node.BlockItems, parent=node) + + def _generate_structs(self): + all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) + + preserved_structs = {} + for name, st in self.structs.items(): + if name not in all_classes: + preserved_structs[name] = st + elif isinstance(st, ir.IdentifiedStructType): + preserved_structs[name] = st + + self.structs.clear() + + for name, st in preserved_structs.items(): + self.structs[name] = st + + # Step 1: 先为所有类创建空的 struct,确保后面可以正确引用 + all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) + for ClassName in all_classes: + is_packed = ClassName in self.class_packed + if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: + Entry = self.SymbolTable[ClassName] + if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + continue + if hasattr(Entry, 'IsEnum') and Entry.IsEnum: + if not getattr(Entry, 'IsRenum', False): + continue + if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: + if hasattr(Entry, 'BaseType') and Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)): + import lib.includes.t as _t + if not isinstance(Entry.BaseType, (_t._CTypedef,)): + continue + if ClassName in self.structs: + if is_packed: + self.structs[ClassName].packed = True + continue + mangled_name = self._mangle_name(ClassName) + struct_type = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed) + self.structs[ClassName] = struct_type + + # Step 2: 解析跨模块的成员类型 + for ClassName, annotations in self.class_member_annotations.items(): + if ClassName not in self.class_members: + continue + for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): + if member_name in annotations: + annotation = annotations[member_name] + ResolvedType = None + + if isinstance(annotation, ast.Attribute): + ClassTypeName = annotation.attr + if ClassTypeName in self.structs: + ResolvedType = self.structs[ClassTypeName] + elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + left = annotation.left + if isinstance(left, ast.Attribute): + ClassTypeName = left.attr + if ClassTypeName in self.structs: + ResolvedType = self.structs[ClassTypeName] + + if ResolvedType: + self.class_members[ClassName][i] = (member_name, ResolvedType) + + struct_name_map = {} + for struct_name, struct in self.structs.items(): + try: + struct_name_map[struct.name] = struct + except AssertionError: + struct_name_map[struct_name] = struct + orig = getattr(struct, '_original_name', None) + if orig: + struct_name_map[orig] = struct + + # Step 3: 更新成员类型,确保使用正确的 mangled struct 引用 + for ClassName in all_classes: + if ClassName not in self.class_members: + continue + for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): + if isinstance(member_type, ir.PointerType): + pointee = member_type.pointee + if isinstance(pointee, ir.IdentifiedStructType): + try: + pname = pointee.name + except AssertionError: + pname = None + struct = struct_name_map.get(pname) if pname else None + if struct is None: + orig = getattr(pointee, '_original_name', None) + struct = struct_name_map.get(orig) if orig else None + if struct is not None: + self.class_members[ClassName][i] = (member_name, ir.PointerType(struct)) + else: + raw_name = pname or '' + if raw_name.startswith('struct.'): + raw_name = raw_name[7:] + new_struct = self._get_or_create_struct(raw_name) + self.class_members[ClassName][i] = (member_name, ir.PointerType(new_struct)) + elif isinstance(member_type, ir.IdentifiedStructType): + try: + mname = member_type.name + except AssertionError: + mname = None + struct = struct_name_map.get(mname) if mname else None + if struct is None: + orig = getattr(member_type, '_original_name', None) + struct = struct_name_map.get(orig) if orig else None + if struct is not None: + self.class_members[ClassName][i] = (member_name, struct) + else: + raw_name = mname or '' + if raw_name.startswith('struct.'): + raw_name = raw_name[7:] + new_struct = self._get_or_create_struct(raw_name) + self.class_members[ClassName][i] = (member_name, new_struct) + + # Step 4: 创建最终的 structs 并设置正确的成员类型 + for ClassName in all_classes: + if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: + Entry = self.SymbolTable[ClassName] + if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + continue + if hasattr(Entry, 'IsEnum') and Entry.IsEnum: + if not getattr(Entry, 'IsRenum', False): + continue + existing_st = self.structs.get(ClassName) + if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0: + # 即使 struct 已有元素,也需要修正 packed 属性 + if ClassName in self.class_packed and not existing_st.packed: + existing_st.packed = True + continue + has_vtable = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes + if not has_vtable: + p = self.class_parent.get(ClassName) + while p: + if p in self.class_vtable or p in self._cross_module_vtable_classes: + has_vtable = True + self.class_vtable.add(ClassName) + break + p = self.class_parent.get(p) + has_bitfield = ClassName in self.class_member_bitfields and any( + self.class_member_bitfields[ClassName].get(name, 0) > 0 + for name, _ in self.class_members.get(ClassName, []) + ) + all_members = self.class_members.get(ClassName, []) + all_bitfield = all( + self.class_member_bitfields.get(ClassName, {}).get(name, 0) > 0 + for name, _ in all_members + ) if all_members else False + + mangled_name = self._mangle_name(ClassName) + + if has_bitfield and all_bitfield: + total_bits = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0) + for name, _ in all_members) + if total_bits <= 8: + storage_type = ir.IntType(8) + elif total_bits <= 16: + storage_type = ir.IntType(16) + elif total_bits <= 32: + storage_type = ir.IntType(32) + else: + storage_type = ir.IntType(64) + member_types = [storage_type] + bitfield_offsets = {} + current_bit_offset = 0 + for name, _ in all_members: + bit_width = self.class_member_bitfields.get(ClassName, {}).get(name, 0) + bitfield_offsets[name] = current_bit_offset + current_bit_offset += bit_width + self.class_member_bitoffsets[ClassName] = bitfield_offsets + else: + member_types = [] + if has_vtable: + member_types.append(ir.PointerType(ir.IntType(8))) + if ClassName in self.class_members: + for _, member_type in self.class_members[ClassName]: + if member_type is None: + member_type = ir.IntType(32) + member_types.append(member_type) + else: + member_types = [ir.IntType(8)] + + # 获取之前创建的 struct 并设置成员 + struct_type = self.structs[ClassName] + if ClassName in self.class_packed: + struct_type.packed = True + # 只在未设置 body 时设置,避免重复定义错误 + if struct_type.elements is None: + struct_type.set_body(*member_types) + + def _create_Vtable_globals(self): + for ClassName, methods in self.class_methods.items(): + if ClassName in self.Vtables: + continue + if not methods: + continue + if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes: + continue + VtableType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) + Vtable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable")) + Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) + Vtable.linkage = 'internal' + self.Vtables[ClassName] = Vtable + + def _fix_global_var_init(self): + for gv_name, gv in list(self.module.globals.items()): + if not isinstance(gv, ir.GlobalVariable): + continue + if gv.linkage in ('external', 'extern_weak'): + continue + needs_fix = False + if gv.initializer is None: + needs_fix = True + elif hasattr(gv.initializer, 'constant') and isinstance(gv.initializer.constant, _Undefined): + needs_fix = True + elif isinstance(gv.initializer, ir.Constant): + if isinstance(gv.initializer.constant, list): + if any(hasattr(c, 'constant') and isinstance(c.constant, _Undefined) for c in gv.initializer.constant): + needs_fix = True + if not needs_fix: + continue + gv.initializer = ir.Constant(gv.value_type, None) + if gv_name.startswith('str_const_') or gv_name.endswith('_Vtable') or gv_name.endswith('_str'): + gv.linkage = 'internal' + + def _zero_value_for_type(self, var_type): + if isinstance(var_type, ir.IntType): + return ir.Constant(var_type, 0) + elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): + return ir.Constant(var_type, 0.0) + elif isinstance(var_type, ir.PointerType): + return ir.Constant(var_type, None) + elif isinstance(var_type, ir.ArrayType): + elem_zv = self._zero_value_for_type(var_type.element) + if elem_zv is None: + return None + return ir.Constant(var_type, [elem_zv] * var_type.count) + elif isinstance(var_type, ir.BaseStructType): + if var_type.elements is not None and len(var_type.elements) > 0: + elem_zvs = [self._zero_value_for_type(m) for m in var_type.elements] + if any(zv is None for zv in elem_zvs): + return None + return ir.Constant(var_type, elem_zvs) + return None + return None + + def _set_Vtable_initializers(self): + for ClassName, methods in self.class_methods.items(): + if ClassName not in self.Vtables: + continue + if not methods: + continue + struct_type = self.structs.get(ClassName) + if not struct_type: + continue + Vtable = self.Vtables[ClassName] + Vtable_entries = [] + for MethodName in methods: + short_name = MethodName.split('.')[-1] if '.' in MethodName else MethodName + full_MethodName = f"{ClassName}.{short_name}" + func = None + if full_MethodName in self.functions: + func = self.functions[full_MethodName] + if func is None: + parent_cls = self.class_parent.get(ClassName) + while parent_cls: + parent_full = f"{parent_cls}.{short_name}" + if parent_full in self.functions: + func = self.functions[parent_full] + break + parent_cls = self.class_parent.get(parent_cls) + if func is None: + Vtable_entries.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) + continue + Vtable_entries.append(func.bitcast(ir.PointerType(ir.IntType(8)))) + Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries) diff --git a/lib/core/LLVMCG/TypeConvert.py b/lib/core/LLVMCG/TypeConvert.py new file mode 100644 index 0000000..ac64018 --- /dev/null +++ b/lib/core/LLVMCG/TypeConvert.py @@ -0,0 +1,618 @@ +from __future__ import annotations +import ast +import llvmlite.ir as ir + + +class TypeConvertMixin: + + def _ctype_to_llvm(self, type_info): + from lib.includes import t as _t + from lib.includes.t import CTypeRegistry + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + + if type_info is None: + return ir.IntType(32) + + if isinstance(type_info, str): + return self._type_str_to_llvm(type_info) + + if not isinstance(type_info, _CTypeInfo): + return ir.IntType(32) + + if type_info.IsFuncPtr: + return ir.IntType(8).as_pointer() + + if type_info.IsState and type_info.PtrCount == 0 and not type_info.IsTypedef: + if type_info.BaseType is None or (isinstance(type_info.BaseType, type) and issubclass(type_info.BaseType, _t.CVoid)) or isinstance(type_info.BaseType, _t.CVoid): + return ir.VoidType() + + if type_info.IsTypedef and type_info.Name: + resolved = self._resolve_typedef_ctype(type_info) + if resolved is not None: + return resolved + + BaseType = self._base_ctype_to_llvm(type_info.BaseType, type_info) + + result = BaseType + for _ in range(type_info.PtrCount): + if isinstance(result, ir.VoidType): + result = ir.IntType(8).as_pointer() + else: + result = ir.PointerType(result) + + for dim in reversed(type_info.ArrayDims): + try: + dim_val = int(dim) + if dim_val > 0: + result = ir.ArrayType(result, dim_val) + except (ValueError, TypeError): + pass + + return result + + def _resolve_typedef_ctype(self, type_info): + from lib.includes import t as _t + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + + name = type_info.Name + if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: + return None + + entry = self.SymbolTable.get(name) + if not entry or not isinstance(entry, _CTypeInfo): + return None + + if entry.BaseType and (not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0): + resolved = entry.Copy() + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + + if entry.OriginalType: + if isinstance(entry.OriginalType, _CTypeInfo): + resolved = entry.OriginalType.Copy() + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + elif isinstance(entry.OriginalType, str): + resolved = _CTypeInfo.FromTypeName(entry.OriginalType) + if resolved and resolved.BaseType: + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + + return None + + def _base_ctype_to_llvm(self, BaseType, type_info=None): + from lib.includes import t as _t + from lib.includes.t import CTypeRegistry + + if BaseType is None: + return ir.VoidType() + + if isinstance(BaseType, (tuple, list)): + elem_types = [self._base_ctype_to_llvm(bt, type_info) for bt in BaseType] + return ir.LiteralStructType(elem_types) if elem_types else ir.IntType(32) + + if isinstance(BaseType, type) and issubclass(BaseType, _t.CType): + BaseType = BaseType() + + if isinstance(BaseType, _t.CVoid): + return ir.VoidType() + + if isinstance(BaseType, _t.CStruct): + struct_name = getattr(BaseType, 'name', '') or (type_info.Name if type_info else '') + if struct_name and struct_name in self.structs: + return self.structs[struct_name] + if struct_name: + return self._get_or_create_struct(struct_name) + return ir.LiteralStructType([]) + + if isinstance(BaseType, (_t.CEnum, _t.REnum)): + enum_name = type_info.Name if type_info else '' + if enum_name and enum_name in self.structs: + return self.structs[enum_name] + return ir.IntType(32) + + if isinstance(BaseType, _t.CUnion): + union_name = type_info.Name if type_info else '' + if union_name and union_name in self.structs: + return self.structs[union_name] + if union_name: + return self._get_or_create_struct(union_name) + return ir.IntType(32) + + if isinstance(BaseType, _t._CTypedef): + typedef_name = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '') + if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable: + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + entry = self.SymbolTable.get(typedef_name) + if entry and isinstance(entry, _CTypeInfo) and entry.BaseType: + if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0: + return self._base_ctype_to_llvm(entry.BaseType, entry) + return ir.IntType(32) + + if isinstance(BaseType, _t.CDefine): + # Use 64-bit type if the define value exceeds 32-bit range + if type_info and hasattr(type_info, 'DefineValue') and isinstance(type_info.DefineValue, int): + if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF: + return ir.IntType(64) + return ir.IntType(32) + + if isinstance(BaseType, _t.CPass): + return ir.VoidType() + + llvm_str = CTypeRegistry.CTypeToLLVM(type(BaseType)) + return self._llvm_str_to_ir(llvm_str) + + def _llvm_str_to_ir(self, llvm_str): + _map = { + 'void': ir.VoidType, 'i1': lambda: ir.IntType(1), + 'i8': lambda: ir.IntType(8), 'i16': lambda: ir.IntType(16), + 'i32': lambda: ir.IntType(32), 'i64': lambda: ir.IntType(64), + 'i128': lambda: ir.IntType(128), 'half': lambda: ir.IntType(16), + 'float': ir.FloatType, 'double': ir.DoubleType, + 'fp128': lambda: ir.IntType(128), 'i8*': lambda: ir.IntType(8).as_pointer(), + 'f8': lambda: ir.IntType(8), 'f16': lambda: ir.IntType(16), + 'f32': ir.FloatType, 'f64': ir.DoubleType, 'f128': lambda: ir.IntType(128), + } + factory = _map.get(llvm_str) + if factory: + return factory() if callable(factory) else factory + return ir.IntType(32) + + def _resolve_typedef(self, type_name: str) -> str: + if type_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + return type_name + if type_name == 'Callable': + return 'Callable' + visited = set() + current = type_name + while current not in visited: + visited.add(current) + if hasattr(self, 'SymbolTable') and self.SymbolTable and current in self.SymbolTable: + Entry = self.SymbolTable[current] + if isinstance(Entry, dict) and Entry.get('type') == 'typedef': + OriginalType = Entry.get('OriginalType', '') + if OriginalType: + current = OriginalType + continue + elif hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: + if hasattr(Entry, 'OriginalType') and Entry.OriginalType: + if isinstance(Entry.OriginalType, _CTypeInfo): + if Entry.OriginalType.IsFuncPtr: + return 'Callable' + return Entry.OriginalType.ToString() if Entry.OriginalType.BaseType else current + elif isinstance(Entry.OriginalType, str): + current = Entry.OriginalType + continue + if hasattr(Entry, 'BaseType') and Entry.BaseType: + from lib.includes import t as _t + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: + resolved = self._resolve_ctype_to_str(Entry) + if resolved and resolved != current: + current = resolved + continue + from lib.core.Handles.HandlesBase import BuiltinTypeMap + bm = BuiltinTypeMap.Get(current) + if bm: + base_cls = bm[0] + try: + instance = base_cls() + cname = getattr(instance, 'CName', '') + if cname: + current = cname + ' *' * bm[1] + continue + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + import logging; logging.warning(f"异常被忽略: {_e}") + pass + from lib.core.Handles.HandlesBase import BuiltinTypeMap + bm = BuiltinTypeMap.Get(current) + if bm and bm[1] > 0: + base_cls = bm[0] + try: + instance = base_cls() + cname = getattr(instance, 'CName', '') + if cname: + current = cname + ' *' * bm[1] + continue + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + import logging; logging.warning(f"异常被忽略: {_e}") + pass + break + return current + + def _resolve_ctype_to_str(self, type_info) -> str: + from lib.includes import t as _t + parts = [] + base = type_info.BaseType + if base is None or base is _t.CVoid or isinstance(base, _t.CVoid): + parts.append('void') + elif isinstance(base, _t._CTypedef) or base is _t._CTypedef: + return '' + elif isinstance(base, _t.CStruct) or base is _t.CStruct: + parts.append(f'struct {getattr(base, "name", "")}') + elif isinstance(base, _t.CEnum) or base is _t.CEnum: + parts.append(f'enum {getattr(base, "name", "")}') + else: + cname = getattr(base, 'CName', '') + if not cname and isinstance(base, type) and issubclass(base, _t.CType): + try: + inst = base() + cname = getattr(inst, 'CName', '') + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + import logging; logging.warning(f"异常被忽略: {_e}") + pass + if cname: + parts.append(cname) + else: + return '' + if type_info.PtrCount > 0: + parts.append('*' * type_info.PtrCount) + return ' '.join(parts) + + def _type_str_to_llvm(self, type_str, IsPtr=False): + type_str = type_str.strip() + cache_key = (type_str, IsPtr) + cached = self._type_cache.get(cache_key) + if cached is not None: + return cached + result = self._type_str_to_llvm_impl(type_str, IsPtr) + if result is not None: + if isinstance(result, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): + self._type_cache[cache_key] = result + elif isinstance(result, ir.PointerType) and isinstance(result.pointee, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): + self._type_cache[cache_key] = result + elif isinstance(result, ir.ArrayType) and not isinstance(result.element, (ir.IdentifiedStructType, ir.LiteralStructType)): + self._type_cache[cache_key] = result + return result + + _CType2LLVM = _type_str_to_llvm + + def _type_str_to_llvm_impl(self, type_str, IsPtr=False): + array_dims = [] + dim_match = __import__('re').findall(r'\[(\d+)\]', type_str) + if dim_match: + array_dims = [int(d) for d in dim_match] + type_str = __import__('re').sub(r'\s*\[\d+\]', '', type_str).strip() + result = self._type_str_to_llvm_base(type_str, IsPtr) + for dim in reversed(array_dims): + result = ir.ArrayType(result, dim) + return result + + def _type_str_to_llvm_base(self, type_str, IsPtr=False): + ptr_depth = 0 + while type_str.endswith('*'): + ptr_depth += 1 + type_str = type_str[:-1].strip() + if ptr_depth > 0: + IsPtr = True + if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + if IsPtr: + result = ir.IntType(8).as_pointer() + for _ in range(ptr_depth - 1): + result = ir.PointerType(result) + return result + return ir.IntType(32) + if type_str in {'const', 'volatile'}: + return ir.IntType(8) + if type_str == 'Callable': + return ir.IntType(8).as_pointer() + if type_str.startswith('const '): + inner_type = self._type_str_to_llvm(type_str[6:].strip(), IsPtr) + return inner_type + if type_str.startswith('volatile '): + inner_type = self._type_str_to_llvm(type_str[9:].strip(), IsPtr) + return inner_type + if type_str.startswith('const_'): + inner_type = self._type_str_to_llvm(type_str[6:], IsPtr) + return inner_type + if type_str.startswith('volatile_'): + inner_type = self._type_str_to_llvm(type_str[9:], IsPtr) + return inner_type + if type_str.startswith('static '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('extern '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('register '): + return self._type_str_to_llvm(type_str[9:].strip(), IsPtr) + if type_str.startswith('inline '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('export '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + resolved = self._resolve_typedef(type_str) + if resolved != type_str: + if '*' in resolved: + IsPtr = False + return self._type_str_to_llvm(resolved, IsPtr) + if type_str.endswith('*'): + BaseType = type_str[:-1].strip() + base_llvm = self._basic_type_to_llvm(BaseType) + if base_llvm is not None and isinstance(base_llvm, ir.VoidType): + result = ir.IntType(8).as_pointer() + for _ in range(ptr_depth): + result = ir.PointerType(result) + return result + if base_llvm is not None and not isinstance(base_llvm, ir.VoidType): + if isinstance(base_llvm, ir.PointerType): + return base_llvm + return ir.PointerType(base_llvm) + if BaseType in self.structs: + return ir.PointerType(self.structs[BaseType]) + if BaseType.startswith('struct '): + stripped = BaseType[7:].strip() + if stripped in self.structs: + return ir.PointerType(self.structs[stripped]) + if '.' in BaseType: + LastPart = BaseType.split('.')[-1] + if LastPart in self.structs: + return ir.PointerType(self.structs[LastPart]) + placeholder = self._get_or_create_struct(LastPart) + return ir.PointerType(placeholder) + if base_llvm is not None and isinstance(base_llvm, ir.VoidType): + return ir.PointerType(ir.IntType(8)) + if type_str.startswith('{') and type_str.endswith('}'): + inner = type_str[1:-1].strip() + elem_strs = [] + depth = 0 + current = '' + for ch in inner: + if ch == ',' and depth == 0: + elem_strs.append(current.strip()) + current = '' + else: + if ch == '{': + depth += 1 + elif ch == '}': + depth -= 1 + current += ch + if current.strip(): + elem_strs.append(current.strip()) + elem_types = [] + for es in elem_strs: + et = self._type_str_to_llvm(es, '*' in es) + if isinstance(et, ir.VoidType): + et = ir.IntType(8).as_pointer() + elem_types.append(et) + if elem_types: + return ir.LiteralStructType(elem_types) + return ir.IntType(32) + if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + return ir.IntType(32) + if type_str.startswith('%'): + stripped = type_str[1:] + if stripped in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + basic_stripped = self._basic_type_to_llvm(stripped) + if basic_stripped is not None: + if IsPtr and not isinstance(basic_stripped, ir.VoidType): + return ir.PointerType(basic_stripped) + return basic_stripped + if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable: + _Entry = self.SymbolTable[type_str] + if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: + resolved_str = self._resolve_typedef(type_str) + if resolved_str != type_str: + return self._type_str_to_llvm(resolved_str, IsPtr) + if hasattr(_Entry, 'BaseType') and _Entry.BaseType: + from lib.includes import t as _t + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: + resolved = self._resolve_ctype_to_str(_Entry) + if resolved: + return self._type_str_to_llvm(resolved, IsPtr) + if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: + if type_str in self.structs: + return self.structs[type_str] + if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if hasattr(_Entry, 'BaseType'): + from lib.includes import t as _t + if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + for ClassName in self.structs: + if type_str == ClassName: + if IsPtr: + return ir.PointerType(self.structs[ClassName]) + return self.structs[ClassName] + if '.' in type_str and not type_str.startswith('%'): + LastPart = type_str.split('.')[-1] + basic_last = self._basic_type_to_llvm(LastPart) + if basic_last is not None: + if IsPtr and not isinstance(basic_last, ir.VoidType): + return ir.PointerType(basic_last) + return basic_last + if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable: + _Entry = self.SymbolTable[LastPart] + if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: + resolved_str = self._resolve_typedef(LastPart) + if resolved_str != LastPart: + return self._type_str_to_llvm(resolved_str, IsPtr) + if hasattr(_Entry, 'BaseType') and _Entry.BaseType: + from lib.includes import t as _t + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: + resolved = self._resolve_ctype_to_str(_Entry) + if resolved: + return self._type_str_to_llvm(resolved, IsPtr) + if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: + if LastPart in self.structs: + return self.structs[LastPart] + if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if hasattr(_Entry, 'BaseType'): + from lib.includes import t as _t + if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if LastPart in self.structs: + if IsPtr: + return ir.PointerType(self.structs[LastPart]) + return self.structs[LastPart] + placeholder = self._get_or_create_struct(LastPart) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('struct '): + stripped = type_str[7:].strip().replace(' *', '').replace('*', '') + if stripped in self.structs: + if IsPtr: + return ir.PointerType(self.structs[stripped]) + return self.structs[stripped] + basic_match = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + placeholder = self._get_or_create_struct(stripped) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('%struct.'): + stripped = type_str[8:].strip().replace(' *', '').replace('*', '') + if stripped in self.structs: + if IsPtr: + return ir.PointerType(self.structs[stripped]) + return self.structs[stripped] + basic_match = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + placeholder = self._get_or_create_struct(stripped) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('union '): + stripped = type_str[6:].strip() + basic_match = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + if type_str.endswith('*'): + pointee = self._type_str_to_llvm(type_str[:-1].strip()) + if isinstance(pointee, ir.VoidType): + return ir.PointerType(ir.IntType(8)) + return ir.PointerType(pointee) + result = self._basic_type_to_llvm(type_str) + if result is None: + result = ir.IntType(32) + if IsPtr: + if isinstance(result, ir.VoidType): + result = ir.PointerType(ir.IntType(8)) + elif isinstance(result, ir.PointerType): + pass + else: + result = ir.PointerType(result) + for _ in range(ptr_depth - 1): + result = ir.PointerType(result) + return result + + def _llvm_str_to_ir(self, llvm_str): + _LLVM_IR_TYPES = { + 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), + 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), + 'i128': ir.IntType(128), 'float': ir.FloatType(), 'double': ir.DoubleType(), + 'half': ir.IntType(16), 'fp128': ir.IntType(128), + } + return _LLVM_IR_TYPES.get(llvm_str) + + def _basic_type_to_llvm(self, type_str): + _LLVM_IR_TYPES = { + 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), + 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), + 'i128': ir.IntType(128), 'f32': ir.FloatType(), 'f64': ir.DoubleType(), + 'half': ir.IntType(16), 'fp128': ir.IntType(128), + } + if type_str in _LLVM_IR_TYPES: + return _LLVM_IR_TYPES[type_str] + from lib.includes.t import CTypeRegistry + resolved = CTypeRegistry.ResolveName(type_str) + if resolved is not None: + ctype_cls, ptr_level = resolved + llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str: + base = self._llvm_str_to_ir(llvm_str) + if base is not None: + for _ in range(ptr_level): + if isinstance(base, ir.VoidType): + base = ir.IntType(8).as_pointer() + else: + base = ir.PointerType(base) + return base + cnameres = CTypeRegistry.CNameToClass(type_str) + if cnameres is not None: + llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) + if llvm_str: + return self._llvm_str_to_ir(llvm_str) + if type_str == '*': + return ir.IntType(8) + if type_str in ('const_', 'const'): + return ir.IntType(8) + return None + + def _is_type_unsigned(self, type_str): + s = type_str.strip() + if s.endswith('*'): + return True + if s.startswith('unsigned'): + return True + from lib.includes.t import CTypeRegistry + resolved = CTypeRegistry.ResolveName(s) + if resolved is not None: + ctype_cls, _ = resolved + try: + inst = ctype_cls() + if getattr(inst, 'IsSigned', None) is False: + return True + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"判断类型符号性失败: {_e}", "Exception") + cnameres = CTypeRegistry.CNameToClass(s) + if cnameres is not None: + try: + inst = cnameres() + if getattr(inst, 'IsSigned', None) is False: + return True + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"判断类型符号性失败: {_e}", "Exception") + return False + + def _record_var_signedness(self, name, type_str_or_bool): + if isinstance(type_str_or_bool, bool): + self.var_signedness[name] = type_str_or_bool + else: + self.var_signedness[name] = self._is_type_unsigned(type_str_or_bool) + + def _is_var_unsigned(self, name): + return self.var_signedness.get(name, False) + + def _check_node_unsigned(self, node): + if isinstance(node, ast.Name): + return self._is_var_unsigned(node.id) + if isinstance(node, ast.BinOp): + return self._check_node_unsigned(node.left) or self._check_node_unsigned(node.right) + if isinstance(node, ast.UnaryOp): + return self._check_node_unsigned(node.operand) + if isinstance(node, ast.Call): + return False + if isinstance(node, ast.Subscript): + return self._check_node_unsigned(node.value) + if isinstance(node, ast.Attribute): + return self._check_node_unsigned(node.value) + return False diff --git a/lib/core/LLVMCG/VaArg.py b/lib/core/LLVMCG/VaArg.py new file mode 100644 index 0000000..b3d5370 --- /dev/null +++ b/lib/core/LLVMCG/VaArg.py @@ -0,0 +1,94 @@ +from __future__ import annotations +import sys +import llvmlite.ir as ir +from lib.core.LLVMCG.BaseGen import VaArgInstruction + + +class VaArgMixin: + + def _get_va_start_intrinsic(self): + if 'llvm.va_start' in self.functions: + return self.functions['llvm.va_start'] + ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) + func = ir.Function(self.module, ftype, name='llvm.va_start') + self.functions['llvm.va_start'] = func + return func + + def _get_va_end_intrinsic(self): + if 'llvm.va_end' in self.functions: + return self.functions['llvm.va_end'] + ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) + func = ir.Function(self.module, ftype, name='llvm.va_end') + self.functions['llvm.va_end'] = func + return func + + def emit_va_start(self, va_list_ptr): + if not self.builder: + return None + func = self._get_va_start_intrinsic() + i8ptr_type = ir.IntType(8).as_pointer() + if va_list_ptr.type == i8ptr_type: + self.builder.call(func, [va_list_ptr]) + else: + ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") + self.builder.call(func, [ptr]) + return None + + def _emit_stack_align(self, alignment=16): + if not self.builder: + return None + void = ir.VoidType() + asm_type = ir.FunctionType(void, []) + mask = -alignment + asm_str = f"andq ${mask}, %rsp" + asm_func = ir.InlineAsm(asm_type, asm_str, "~{dirflag},~{fpsr},~{flags},~{rsp}", side_effect=True) + self.builder.call(asm_func, [], name="align_stack") + return None + + def emit_va_end(self, va_list_ptr): + if not self.builder: + return None + func = self._get_va_end_intrinsic() + i8ptr_type = ir.IntType(8).as_pointer() + if va_list_ptr.type == i8ptr_type: + self.builder.call(func, [va_list_ptr]) + else: + ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") + self.builder.call(func, [ptr]) + return None + + def emit_va_arg(self, va_list_ptr, arg_type): + if not self.builder: + return self._ZeroConst(arg_type) + if not hasattr(self, '_va_arg_counter'): + self._va_arg_counter = 0 + self._va_arg_counter += 1 + import sys + is_x86_64 = sys.platform in ('win32', 'win64', 'windows', 'linux', 'linux2', 'darwin') + if is_x86_64: + if isinstance(arg_type, ir.PointerType): + va_arg_type = ir.IntType(64) + elif isinstance(arg_type, (ir.FloatType, ir.DoubleType)): + va_arg_type = ir.DoubleType() + elif isinstance(arg_type, ir.IntType) and arg_type.width < 64: + va_arg_type = ir.IntType(64) + else: + va_arg_type = arg_type + instr = VaArgInstruction(self.builder.block, va_arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') + self.builder._insert(instr) + if va_arg_type != arg_type: + if isinstance(arg_type, ir.PointerType): + result = self.builder.inttoptr(instr, arg_type, name=f'va_arg_ptr_{self._va_arg_counter}') + elif isinstance(arg_type, ir.FloatType): + result = self.builder.fptrunc(instr, arg_type, name=f'va_arg_fptrunc_{self._va_arg_counter}') + else: + result = self.builder.trunc(instr, arg_type, name=f'va_arg_trunc_{self._va_arg_counter}') + else: + result = instr + return result + else: + if isinstance(arg_type, ir.IntType) and arg_type.width < 64: + arg_type = ir.IntType(64) + instr = VaArgInstruction(self.builder.block, arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') + self.builder._insert(instr) + return instr diff --git a/lib/core/LLVMCG/__init__.py b/lib/core/LLVMCG/__init__.py new file mode 100644 index 0000000..6b231e9 --- /dev/null +++ b/lib/core/LLVMCG/__init__.py @@ -0,0 +1,34 @@ +""" +LLVMCG 包 - LLVM 代码生成器模块 + +将 LlvmCodeGenerator.py 拆分为多个 Mixin 模块: +- BaseGen: 基础设施(__init__、平台解析、名称修饰、函数查找) +- TypeConvert: 类型转换(CType -> LLVM IR 类型) +- StructGen: 结构体生成(struct/vtable 定义与初始化) +- MemoryOps: 内存操作(alloca/Load/store/coerce) +- ExprGen: 表达式生成(常量、二元运算、返回、printf) +- FuncGen: 函数处理(参数调整、成员偏移、函数声明) +- VaArg: 变长参数处理(va_start/va_end/va_arg) +""" + +from lib.core.LLVMCG.BaseGen import ( + BaseGenMixin, + VaArgInstruction, +) +from lib.core.LLVMCG.TypeConvert import TypeConvertMixin +from lib.core.LLVMCG.StructGen import StructGenMixin +from lib.core.LLVMCG.MemoryOps import MemoryOpsMixin +from lib.core.LLVMCG.ExprGen import ExprGenMixin +from lib.core.LLVMCG.FuncGen import FuncGenMixin +from lib.core.LLVMCG.VaArg import VaArgMixin + +__all__ = [ + 'BaseGenMixin', + 'TypeConvertMixin', + 'StructGenMixin', + 'MemoryOpsMixin', + 'ExprGenMixin', + 'FuncGenMixin', + 'VaArgMixin', + 'VaArgInstruction', +] diff --git a/lib/core/LlvmCodeGenerator.py b/lib/core/LlvmCodeGenerator.py index 2f3c786..78fbd1c 100644 --- a/lib/core/LlvmCodeGenerator.py +++ b/lib/core/LlvmCodeGenerator.py @@ -1,2556 +1,46 @@ -import re -import ast -import os -import hashlib +# LLVM 代码生成器主类 +# 通过 Mixin 模式组合各功能模块,保持向后兼容的导入路径 +# +# 拆分后的模块位于 lib/core/LLVMCG/ 目录下: +# - BaseGen.py: __init__、平台解析、名称修饰、函数查找 +# - TypeConvert.py: 类型转换(CType -> LLVM IR) +# - StructGen.py: 结构体生成(struct/vtable) +# - MemoryOps.py: 内存操作(alloca/Load/store) +# - ExprGen.py: 表达式生成(常量、二元运算、返回) +# - FuncGen.py: 函数处理(参数调整、成员偏移) +# - VaArg.py: 变长参数处理 + +from lib.core.LLVMCG.BaseGen import BaseGenMixin, VaArgInstruction +from lib.core.LLVMCG.TypeConvert import TypeConvertMixin +from lib.core.LLVMCG.StructGen import StructGenMixin +from lib.core.LLVMCG.MemoryOps import MemoryOpsMixin +from lib.core.LLVMCG.ExprGen import ExprGenMixin +from lib.core.LLVMCG.FuncGen import FuncGenMixin +from lib.core.LLVMCG.VaArg import VaArgMixin + +# from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin + import llvmlite.ir as ir -from llvmlite.ir.values import _Undefined -from lib.core.AsmIntelToAtt import convert as _intel_to_att -TYPEDEF_NAMES = {'UINT', 'INT', 'BYTE', 'BYTEPTR', 'WORD', 'DWORD', 'QWORD', - 'INT8', 'INT16', 'INT32', 'INT64', 'UINT8', 'UINT16', 'UINT32', 'UINT64', - 'INTPTR', 'UINTPTR', 'SIZE_T', 'SSIZE_T', 'PTRDIFF_T', - 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', - 'atomic_int', 'atomic_uint', 'atomic_long', 'atomic_ulong', - 'atomic_int8', 'atomic_uint8', 'atomic_int16', 'atomic_uint16', - 'atomic_int32', 'atomic_uint32', 'atomic_int64', 'atomic_uint64', - 'atomic_ptr', 'atomic_flag', 'typedef', - 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', - 'BOOL', 'type'} +class LlvmCodeGenerator( + BaseGenMixin, + TypeConvertMixin, + StructGenMixin, + MemoryOpsMixin, + ExprGenMixin, + FuncGenMixin, + VaArgMixin, +): + """LLVM IR 代码生成器 -class VaArgInstruction(ir.Instruction): - def descr(self, buf): - ptr = self.operands[0] - buf.append("va_arg {0} {1}, {2}\n".format( - ptr.type, ptr.get_reference(), self.type)) + 通过 Mixin 模式组合各功能模块。 + 实际方法实现分布在 lib/core/LLVMCG/ 下的各模块中。 + """ + #builder: ir.IRBuilder = None + #_Trans: LlvmGeneratorMixin = None + pass -class LlvmCodeGenerator: - - @staticmethod - def _parse_triple(triple): - """解析目标三元组,返回平台信息字典""" - info = { - 'is_windows': False, 'is_linux': False, 'is_macos': False, - 'is_x86_64': False, 'is_arm64': False, 'is_32bit': False, - 'ptr_size': 8, 'long_size': 8, 'wchar_t_size': 32, - } - if not triple: - return info - triple_lower = triple.lower() - # 检测操作系统 - if 'windows' in triple_lower or 'win32' in triple_lower or 'mingw' in triple_lower or 'msvc' in triple_lower or 'cygwin' in triple_lower: - info['is_windows'] = True - # Windows LLP64: long = 32 位, wchar_t = 16 位 - info['long_size'] = 32 - info['wchar_t_size'] = 16 - elif 'linux' in triple_lower: - info['is_linux'] = True - elif 'darwin' in triple_lower or 'macos' in triple_lower or 'apple' in triple_lower: - info['is_macos'] = True - # 检测架构 - if 'x86_64' in triple_lower or 'amd64' in triple_lower or 'x64' in triple_lower: - info['is_x86_64'] = True - elif 'aarch64' in triple_lower or 'arm64' in triple_lower: - info['is_arm64'] = True - elif 'i386' in triple_lower or 'i686' in triple_lower or 'arm' in triple_lower: - info['is_32bit'] = True - info['ptr_size'] = 4 - info['long_size'] = 32 - if info['is_windows']: - info['wchar_t_size'] = 16 - else: - info['wchar_t_size'] = 32 - return info - - def __init__(self, triple=None, datalayout=None): - self.module = ir.Module(name="transpyc_module") - if triple: - self.module.triple = triple - else: - self.module.triple = "x86_64-none-elf" - if datalayout: - self.module.data_layout = datalayout - else: - self.module.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - - # 解析目标平台信息 - self._platform_info = self._parse_triple(self.module.triple) - self.ptr_size = self._platform_info['ptr_size'] - # 根据目标平台配置 t 模块中的平台相关类型大小 - import t as _t - _t.configure_platform(self.module.triple) - self.builder = None - self.func = None - self.functions = {} - self.variables = {} - self._direct_values = {} - self._reg_values = {} - self.var_signedness = {} - self._unsigned_results = {} - self.string_const_counter = 0 - self.Vtables = {} - self.class_methods = {} - self.class_members = {} - self.class_member_defaults = {} - self.class_member_signeds = {} - self.class_member_bitfields = {} - self.class_member_byteorders = {} - self.class_member_element_class = {} - self.class_member_bitoffsets = {} - self.structs = {} - self._cross_module_vtable_classes = set() - self.class_vtable = set() - self.class_parent = {} - # Store member annotations for deferred type resolution (cross-module class references) - self.class_member_annotations = {} - self.loop_break_targets = [] - self.loop_continue_targets = [] - self.eh_jmp_buf_stack = [] - self.eh_except_block_stack = [] - self.eh_finally_stack = [] - self.global_vars = set() - self.nonlocal_params = {} - self._variable_scope_stack = [] # Stack of outer scope variables for nested function nonlocal lookup - self.var_struct_class = {} - self.global_struct_class = {} - self.var_type_info = {} - self.var_const_flags = {} - self._current_source_file = None - self._current_source_lines = [] - self._ns_cache = {} - self._type_cache = {} - self._typedef_cache = {} - self._func_sig_cache = {} - self.var_type_assignments = {} - self._temp_struct_ptrs = [] - self._stop_iter_flag_param = None - self._local_heap_ptrs = [] - self._var_to_heap_ptr = {} - self.known_return_types = {} - self._current_lineno = 0 - self._current_node_info = "" - self.module_sha1 = None - self.module_sha1_map = {} - self._temp_dir = None - self._export_funcs = set() - self._export_extern_funcs = set() - self._current_module_func_names = set() - self.class_packed = set() - self._define_constants = {} - pi = self._platform_info - # 根据目标平台设置宏(声明式,从三元组推导) - if pi['is_windows']: - self._define_constants['_WIN32'] = 1 - if not pi['is_32bit']: - self._define_constants['_WIN64'] = 1 - self._define_constants['WIN64'] = 1 - self._define_constants['WIN32'] = 1 - if pi['is_linux']: - self._define_constants['__linux__'] = 1 - if pi['is_macos']: - self._define_constants['__APPLE__'] = 1 - self._define_constants['__MACH__'] = 1 - if pi['is_x86_64']: - self._define_constants['__x86_64__'] = 1 - self._define_constants['__x86_64'] = 1 - self._define_constants['_M_X64'] = 1 - elif pi['is_arm64']: - self._define_constants['__aarch64__'] = 1 - self._define_constants['_M_ARM64'] = 1 - if not pi['is_32bit'] and pi['is_linux']: - self._define_constants['__LP64__'] = 1 - elif pi['is_32bit']: - self._define_constants['_ILP32'] = 1 - self._define_constants['SIZEOF_VOID_P'] = pi['ptr_size'] - self._define_constants['__SIZEOF_POINTER__'] = pi['ptr_size'] - - def find_struct_by_pointee(self, pointee): - """根据 pointee 类型查找匹配的结构体,返回 (class_name, struct_type) 或 None""" - for class_name, struct_type in self.structs.items(): - if pointee == struct_type: - return (class_name, struct_type) - return None - - def _get_or_create_struct(self, name, source_sha1=None, packed=False): - clean_name = name.replace(' *', '').replace('*', '').replace(' ', '_').replace('const', 'const_').replace('volatile', 'volatile_') - if clean_name in self.structs: - existing = self.structs[clean_name] - if packed and isinstance(existing, ir.IdentifiedStructType) and not existing.packed: - existing.packed = True - return existing - if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}: - return ir.IntType(8) - if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable: - Entry = self.SymbolTable[clean_name] - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - resolved_str = self._resolve_typedef(clean_name) - if resolved_str != clean_name: - return self._type_str_to_llvm(resolved_str) - if hasattr(Entry, 'BaseType') and Entry.BaseType: - from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: - resolved = self._resolve_ctype_to_str(Entry) - if resolved: - return self._type_str_to_llvm(resolved) - if hasattr(Entry, 'IsRenum') and Entry.IsRenum: - if clean_name in self.structs: - return self.structs[clean_name] - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: - return ir.IntType(32) - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: - return ir.IntType(32) - if hasattr(Entry, 'BaseType'): - from lib.includes import t as _t - if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): - return ir.IntType(32) - if Entry.BaseType is _t.CEnum: - return ir.IntType(32) - if source_sha1: - ns_name = f"{source_sha1}.{clean_name}" - elif hasattr(self, '_struct_sha1_map') and clean_name in self._struct_sha1_map: - ns_name = f"{self._struct_sha1_map[clean_name]}.{clean_name}" - else: - ns_name = self._mangle_name(clean_name) - st = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed) - self.structs[clean_name] = st - return st - - def _set_node_info(self, node, extra_info=""): - if hasattr(node, 'lineno'): - self._current_lineno = node.lineno - else: - self._current_lineno = 0 - if hasattr(node, 'col_offset'): - self._current_node_info = f"line {self._current_lineno}, col {node.col_offset}" - else: - self._current_node_info = f"line {self._current_lineno}" - if extra_info: - self._current_node_info += f" ({extra_info})" - - def _set_source_info(self, filepath): - self._current_source_file = filepath - try: - with open(filepath, 'r', encoding='utf-8') as f: - self._current_source_lines = f.readlines() - except Exception: # 文件读取失败时回退为空行列表 - self._current_source_lines = [] - - def _ns_hash(self): - if 'workspace' in self._ns_cache: - return self._ns_cache['workspace'] - cwd = os.getcwd().replace('\\', '/').lower() - digest = hashlib.sha1(cwd.encode('utf-8')).hexdigest()[:12] - self._ns_cache['workspace'] = digest - return digest - - def _skip_mangle(self, name): - skip_prefixes = ('llvm.', 'str_const_', 'printf', 'memset_pattern') - if any(name.startswith(p) for p in skip_prefixes): - return True - if '.' in name: - parts = name.split('.', 1) - if len(parts[0]) >= 8 and all(c in '0123456789abcdef' for c in parts[0]): - return True - return False - - def _mangle_name(self, name): - if self._skip_mangle(name): - return name - if name in self._export_funcs: - return name - if self.module_sha1: - return f"{self.module_sha1}.{name}" - return name - - def _find_function(self, name): - if name in self.functions: - return self.functions[name] - g = self.module.globals.get(name) - if g and isinstance(g, ir.Function): - self.functions[name] = g - return g - mangled = self._mangle_func_name(name) - if mangled != name: - if mangled in self.functions: - self.functions[name] = self.functions[mangled] - return self.functions[mangled] - g = self.module.globals.get(mangled) - if g and isinstance(g, ir.Function): - self.functions[mangled] = g - self.functions[name] = g - return g - for sha1 in self.module_sha1_map.values(): - prefixed = f"{sha1}.{name}" - if prefixed in self.functions: - self.functions[name] = self.functions[prefixed] - return self.functions[prefixed] - g = self.module.globals.get(prefixed) - if g and isinstance(g, ir.Function): - self.functions[prefixed] = g - self.functions[name] = g - return g - return None - - def _has_function(self, name): - return self._find_function(name) is not None - - def _get_or_declare_function(self, mangled_name, func_type): - for g in self.module.globals: - if isinstance(g, ir.Function) and g.name == mangled_name: - return g - return ir.Function(self.module, func_type, name=mangled_name) - - def _get_function(self, name): - func = self._find_function(name) - return func - - def _mangle_func_name(self, name, module_name=None): - if name in self._export_funcs: - return name - if name in self._export_extern_funcs and name not in self._current_module_func_names: - return name - # main 函数作为程序入口点,永远不混淆 - if name == 'main': - return name - # Try class_sha1_map first for class methods (e.g., 'md5.__init__' -> class 'md5') - class_sha1_map = getattr(self, 'class_sha1_map', {}) - if class_sha1_map: - if '.' in name: - base_class = name.split('.')[0] - if base_class in class_sha1_map: - sha1 = class_sha1_map[base_class] - return f"{sha1}.{name}" - elif name in class_sha1_map: - sha1 = class_sha1_map[name] - return f"{sha1}.{name}" - # If module_name is already a SHA1 hash (16 hex chars), use it directly - if module_name and len(module_name) == 16 and all(c in '0123456789abcdef' for c in module_name): - return f"{module_name}.{name}" - if module_name and module_name in self.module_sha1_map: - sha1 = self.module_sha1_map[module_name] - return f"{sha1}.{name}" - # Try parent package name (e.g., 'hashlib' -> 'hashlib.__init__') - if module_name: - init_name = f"{module_name}.__init__" - if init_name in self.module_sha1_map: - sha1 = self.module_sha1_map[init_name] - return f"{sha1}.{name}" - if self._skip_mangle(name): - return name - if self.module_sha1: - return f"{self.module_sha1}.{name}" - return name - - def _get_source_line(self, lineno): - if 0 < lineno <= len(self._current_source_lines): - return self._current_source_lines[lineno - 1].rstrip('\r\n') - return None - - def _get_node_info(self): - info = "" - if self._current_node_info: - info = f" [{self._current_node_info}]" - if self._current_source_file: - info += f" in {self._current_source_file}" - lineno = self._current_lineno - if lineno > 0: - info += f", line {lineno}:" - source_line = self._get_source_line(lineno) - if source_line: - info += f"\n → {source_line}" - return info - - def _register_local_heap_ptr(self, val, ClassName=None, VarName=None): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - self._local_heap_ptrs.append((val, 'struct', ClassName)) - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - self._local_heap_ptrs.append((val, 'i8', ClassName)) - if VarName: - self._var_to_heap_ptr[VarName] = val - - def _unregister_local_heap_ptr(self, val): - self._local_heap_ptrs = [(v, t, cn) for v, t, cn in self._local_heap_ptrs if v is not val] - - def _emit_local_heap_frees(self): - if not self._local_heap_ptrs or not self.builder: - return - # 创建一个集合来跟踪已经删除的对象 - deleted_objects = set() - for ptr, ptr_type, ClassName in self._local_heap_ptrs: - # 先检查指针是否为 null - if ptr_type == 'i8': - # 对于 i8* 类型的指针,加载其值并检查是否为 null - loaded_ptr = self.builder.load(ptr, name="load_ptr") - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - is_null = self.builder.icmp_unsigned('==', loaded_ptr, null_ptr, name="is_null") - # 创建一个基本块来处理非 null 的情况 - not_null_block = self.builder.append_basic_block(name="not_null") - # 创建一个基本块来处理下一个对象 - next_block = self.builder.append_basic_block(name="next") - # 如果指针为 null,跳转到下一个对象 - self.builder.cbranch(is_null, next_block, not_null_block) - # 切换到非 null 的基本块 - self.builder.position_at_end(not_null_block) - # 然后调用 __del__ 方法 - if ClassName and self._has_function(f'{ClassName}.__del__'): - if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: - cast_ptr = self.builder.bitcast(ptr, ir.PointerType(self.structs[ClassName]), name=f"cast_{ClassName}") - else: - cast_ptr = ptr - if cast_ptr not in deleted_objects: - self.builder.call(self._get_function(f'{ClassName}.__del__'), [cast_ptr], name=f"call_{ClassName}.__del__") - deleted_objects.add(cast_ptr) - # 最后释放内存 - if ptr_type == 'struct': - raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="local_free_cast") - elif ptr_type == 'i8': - raw = ptr - else: - continue - free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) - free_func = self._get_or_declare_func('free', free_type) - self.builder.call(free_func, [raw]) - # 如果是 i8* 类型的指针,跳转到下一个对象 - if ptr_type == 'i8': - self.builder.branch(next_block) - # 切换到下一个对象的基本块 - self.builder.position_at_end(next_block) - self._local_heap_ptrs = [] - - def _register_temp_ptr(self, val): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - for CN, ST in self.structs.items(): - if pointee == ST: - self._temp_struct_ptrs.append(val) - return - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - self._temp_struct_ptrs.append(val) - - def _unregister_temp_ptr(self, val): - self._temp_struct_ptrs = [t for t in self._temp_struct_ptrs if t is not val] - - def _emit_temp_frees(self): - if not self._temp_struct_ptrs or not self.builder: - return - for ptr in self._temp_struct_ptrs: - if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="free_cast") - elif isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: - raw = ptr - else: - continue - free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) - free_func = self._get_or_declare_func('free', free_type) - self.builder.call(free_func, [raw]) - self._temp_struct_ptrs = [] - - def setup_from_symbol_table(self, SymbolTable): - self.SymbolTable = SymbolTable - for name, info in SymbolTable.items(): - if not isinstance(info, dict): - if hasattr(info, 'get'): - info = dict(info) if hasattr(info, '__iter__') else {} - else: - continue - TypeKind = info.get('type', '') - if TypeKind == 'struct': - ClassName = name - self.class_methods[ClassName] = [] - self.class_members[ClassName] = [] - members = info.get('members', {}) - if members: - for MemberName, MemberInfo in members.items(): - if isinstance(MemberInfo, dict): - MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False)) - self.class_members[ClassName].append((MemberName, MemberType)) - elif isinstance(MemberInfo, _CTypeInfo): - MemberType = self._ctype_to_llvm(MemberInfo) - if MemberType is None: - MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr) - self.class_members[ClassName].append((MemberName, MemberType)) - self._generate_structs() - self._create_Vtable_globals() - - def register_method(self, ClassName, MethodName): - if ClassName not in self.class_methods: - self.class_methods[ClassName] = [] - if ClassName not in self.class_members: - self.class_members[ClassName] = [] - self._generate_structs() - self._create_Vtable_globals() - if MethodName not in self.class_methods[ClassName]: - self.class_methods[ClassName].append(MethodName) - - def _ctype_to_llvm(self, type_info): - from lib.includes import t as _t - from lib.includes.t import CTypeRegistry - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - - if type_info is None: - return ir.IntType(32) - - if isinstance(type_info, str): - return self._type_str_to_llvm(type_info) - - if not isinstance(type_info, _CTypeInfo): - return ir.IntType(32) - - if type_info.IsFuncPtr: - return ir.IntType(8).as_pointer() - - if type_info.IsState and type_info.PtrCount == 0 and not type_info.IsTypedef: - if type_info.BaseType is None or (isinstance(type_info.BaseType, type) and issubclass(type_info.BaseType, _t.CVoid)) or isinstance(type_info.BaseType, _t.CVoid): - return ir.VoidType() - - if type_info.IsTypedef and type_info.Name: - resolved = self._resolve_typedef_ctype(type_info) - if resolved is not None: - return resolved - - base_type = self._base_ctype_to_llvm(type_info.BaseType, type_info) - - result = base_type - for _ in range(type_info.PtrCount): - if isinstance(result, ir.VoidType): - result = ir.IntType(8).as_pointer() - else: - result = ir.PointerType(result) - - for dim in reversed(type_info.ArrayDims): - try: - dim_val = int(dim) - if dim_val > 0: - result = ir.ArrayType(result, dim_val) - except (ValueError, TypeError): - pass - - return result - - def _resolve_typedef_ctype(self, type_info): - from lib.includes import t as _t - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - - name = type_info.Name - if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: - return None - - entry = self.SymbolTable.get(name) - if not entry or not isinstance(entry, _CTypeInfo): - return None - - if entry.BaseType and (not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0): - resolved = entry.Copy() - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - - if entry.OriginalType: - if isinstance(entry.OriginalType, _CTypeInfo): - resolved = entry.OriginalType.Copy() - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - elif isinstance(entry.OriginalType, str): - resolved = _CTypeInfo.FromTypeName(entry.OriginalType) - if resolved and resolved.BaseType: - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - - return None - - def _base_ctype_to_llvm(self, base_type, type_info=None): - from lib.includes import t as _t - from lib.includes.t import CTypeRegistry - - if base_type is None: - return ir.VoidType() - - if isinstance(base_type, (tuple, list)): - elem_types = [self._base_ctype_to_llvm(bt, type_info) for bt in base_type] - return ir.LiteralStructType(elem_types) if elem_types else ir.IntType(32) - - if isinstance(base_type, type) and issubclass(base_type, _t.CType): - base_type = base_type() - - if isinstance(base_type, _t.CVoid): - return ir.VoidType() - - if isinstance(base_type, _t.CStruct): - struct_name = getattr(base_type, 'name', '') or (type_info.Name if type_info else '') - if struct_name and struct_name in self.structs: - return self.structs[struct_name] - if struct_name: - return self._get_or_create_struct(struct_name) - return ir.LiteralStructType([]) - - if isinstance(base_type, (_t.CEnum, _t.REnum)): - enum_name = type_info.Name if type_info else '' - if enum_name and enum_name in self.structs: - return self.structs[enum_name] - return ir.IntType(32) - - if isinstance(base_type, _t.CUnion): - union_name = type_info.Name if type_info else '' - if union_name and union_name in self.structs: - return self.structs[union_name] - if union_name: - return self._get_or_create_struct(union_name) - return ir.IntType(32) - - if isinstance(base_type, _t._CTypedef): - typedef_name = getattr(base_type, 'value', '') or (type_info.Name if type_info else '') - if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable: - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - entry = self.SymbolTable.get(typedef_name) - if entry and isinstance(entry, _CTypeInfo) and entry.BaseType: - if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0: - return self._base_ctype_to_llvm(entry.BaseType, entry) - return ir.IntType(32) - - if isinstance(base_type, _t.CDefine): - # Use 64-bit type if the define value exceeds 32-bit range - if type_info and hasattr(type_info, 'DefineValue') and isinstance(type_info.DefineValue, int): - if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF: - return ir.IntType(64) - return ir.IntType(32) - - if isinstance(base_type, _t.CPass): - return ir.VoidType() - - llvm_str = CTypeRegistry.CTypeToLLVM(type(base_type)) - return self._llvm_str_to_ir(llvm_str) - - def _llvm_str_to_ir(self, llvm_str): - _map = { - 'void': ir.VoidType, 'i1': lambda: ir.IntType(1), - 'i8': lambda: ir.IntType(8), 'i16': lambda: ir.IntType(16), - 'i32': lambda: ir.IntType(32), 'i64': lambda: ir.IntType(64), - 'i128': lambda: ir.IntType(128), 'half': lambda: ir.IntType(16), - 'float': ir.FloatType, 'double': ir.DoubleType, - 'fp128': lambda: ir.IntType(128), 'i8*': lambda: ir.IntType(8).as_pointer(), - 'f8': lambda: ir.IntType(8), 'f16': lambda: ir.IntType(16), - 'f32': ir.FloatType, 'f64': ir.DoubleType, 'f128': lambda: ir.IntType(128), - } - factory = _map.get(llvm_str) - if factory: - return factory() if callable(factory) else factory - return ir.IntType(32) - - def _resolve_typedef(self, type_name: str) -> str: - if type_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return type_name - if type_name == 'Callable': - return 'Callable' - visited = set() - current = type_name - while current not in visited: - visited.add(current) - if hasattr(self, 'SymbolTable') and self.SymbolTable and current in self.SymbolTable: - Entry = self.SymbolTable[current] - if isinstance(Entry, dict) and Entry.get('type') == 'typedef': - OriginalType = Entry.get('OriginalType', '') - if OriginalType: - current = OriginalType - continue - elif hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - if hasattr(Entry, 'OriginalType') and Entry.OriginalType: - if isinstance(Entry.OriginalType, _CTypeInfo): - if Entry.OriginalType.IsFuncPtr: - return 'Callable' - return Entry.OriginalType.ToString() if Entry.OriginalType.BaseType else current - elif isinstance(Entry.OriginalType, str): - current = Entry.OriginalType - continue - if hasattr(Entry, 'BaseType') and Entry.BaseType: - from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: - resolved = self._resolve_ctype_to_str(Entry) - if resolved and resolved != current: - current = resolved - continue - from lib.core.Handles.HandlesBase import BuiltinTypeMap - bm = BuiltinTypeMap.Get(current) - if bm: - base_cls = bm[0] - try: - instance = base_cls() - cname = getattr(instance, 'CName', '') - if cname: - current = cname + ' *' * bm[1] - continue - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - from lib.core.Handles.HandlesBase import BuiltinTypeMap - bm = BuiltinTypeMap.Get(current) - if bm and bm[1] > 0: - base_cls = bm[0] - try: - instance = base_cls() - cname = getattr(instance, 'CName', '') - if cname: - current = cname + ' *' * bm[1] - continue - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - break - return current - - def _resolve_ctype_to_str(self, type_info) -> str: - from lib.includes import t as _t - parts = [] - base = type_info.BaseType - if base is None or base is _t.CVoid or isinstance(base, _t.CVoid): - parts.append('void') - elif isinstance(base, _t._CTypedef) or base is _t._CTypedef: - return '' - elif isinstance(base, _t.CStruct) or base is _t.CStruct: - parts.append(f'struct {getattr(base, "name", "")}') - elif isinstance(base, _t.CEnum) or base is _t.CEnum: - parts.append(f'enum {getattr(base, "name", "")}') - else: - cname = getattr(base, 'CName', '') - if not cname and isinstance(base, type) and issubclass(base, _t.CType): - try: - inst = base() - cname = getattr(inst, 'CName', '') - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - if cname: - parts.append(cname) - else: - return '' - if type_info.PtrCount > 0: - parts.append('*' * type_info.PtrCount) - return ' '.join(parts) - - def _type_str_to_llvm(self, type_str, IsPtr=False): - type_str = type_str.strip() - cache_key = (type_str, IsPtr) - cached = self._type_cache.get(cache_key) - if cached is not None: - return cached - result = self._type_str_to_llvm_impl(type_str, IsPtr) - if result is not None: - if isinstance(result, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): - self._type_cache[cache_key] = result - elif isinstance(result, ir.PointerType) and isinstance(result.pointee, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): - self._type_cache[cache_key] = result - elif isinstance(result, ir.ArrayType) and not isinstance(result.element, (ir.IdentifiedStructType, ir.LiteralStructType)): - self._type_cache[cache_key] = result - return result - - _CType2LLVM = _type_str_to_llvm - - def _type_str_to_llvm_impl(self, type_str, IsPtr=False): - array_dims = [] - dim_match = __import__('re').findall(r'\[(\d+)\]', type_str) - if dim_match: - array_dims = [int(d) for d in dim_match] - type_str = __import__('re').sub(r'\s*\[\d+\]', '', type_str).strip() - result = self._type_str_to_llvm_base(type_str, IsPtr) - for dim in reversed(array_dims): - result = ir.ArrayType(result, dim) - return result - - def _type_str_to_llvm_base(self, type_str, IsPtr=False): - ptr_depth = 0 - while type_str.endswith('*'): - ptr_depth += 1 - type_str = type_str[:-1].strip() - if ptr_depth > 0: - IsPtr = True - if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - if IsPtr: - result = ir.IntType(8).as_pointer() - for _ in range(ptr_depth - 1): - result = ir.PointerType(result) - return result - return ir.IntType(32) - if type_str in {'const', 'volatile'}: - return ir.IntType(8) - if type_str == 'Callable': - return ir.IntType(8).as_pointer() - if type_str.startswith('const '): - inner_type = self._type_str_to_llvm(type_str[6:].strip(), IsPtr) - return inner_type - if type_str.startswith('volatile '): - inner_type = self._type_str_to_llvm(type_str[9:].strip(), IsPtr) - return inner_type - if type_str.startswith('const_'): - inner_type = self._type_str_to_llvm(type_str[6:], IsPtr) - return inner_type - if type_str.startswith('volatile_'): - inner_type = self._type_str_to_llvm(type_str[9:], IsPtr) - return inner_type - if type_str.startswith('static '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('extern '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('register '): - return self._type_str_to_llvm(type_str[9:].strip(), IsPtr) - if type_str.startswith('inline '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('export '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - resolved = self._resolve_typedef(type_str) - if resolved != type_str: - if '*' in resolved: - IsPtr = False - return self._type_str_to_llvm(resolved, IsPtr) - if type_str.endswith('*'): - base_type = type_str[:-1].strip() - base_llvm = self._basic_type_to_llvm(base_type) - if base_llvm is not None and isinstance(base_llvm, ir.VoidType): - result = ir.IntType(8).as_pointer() - for _ in range(ptr_depth): - result = ir.PointerType(result) - return result - if base_llvm is not None and not isinstance(base_llvm, ir.VoidType): - if isinstance(base_llvm, ir.PointerType): - return base_llvm - return ir.PointerType(base_llvm) - if base_type in self.structs: - return ir.PointerType(self.structs[base_type]) - if base_type.startswith('struct '): - stripped = base_type[7:].strip() - if stripped in self.structs: - return ir.PointerType(self.structs[stripped]) - if '.' in base_type: - last_part = base_type.split('.')[-1] - if last_part in self.structs: - return ir.PointerType(self.structs[last_part]) - placeholder = self._get_or_create_struct(last_part) - return ir.PointerType(placeholder) - if base_llvm is not None and isinstance(base_llvm, ir.VoidType): - return ir.PointerType(ir.IntType(8)) - if type_str.startswith('{') and type_str.endswith('}'): - inner = type_str[1:-1].strip() - elem_strs = [] - depth = 0 - current = '' - for ch in inner: - if ch == ',' and depth == 0: - elem_strs.append(current.strip()) - current = '' - else: - if ch == '{': - depth += 1 - elif ch == '}': - depth -= 1 - current += ch - if current.strip(): - elem_strs.append(current.strip()) - elem_types = [] - for es in elem_strs: - et = self._type_str_to_llvm(es, '*' in es) - if isinstance(et, ir.VoidType): - et = ir.IntType(8).as_pointer() - elem_types.append(et) - if elem_types: - return ir.LiteralStructType(elem_types) - return ir.IntType(32) - if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return ir.IntType(32) - if type_str.startswith('%'): - stripped = type_str[1:] - if stripped in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - basic_stripped = self._basic_type_to_llvm(stripped) - if basic_stripped is not None: - if IsPtr and not isinstance(basic_stripped, ir.VoidType): - return ir.PointerType(basic_stripped) - return basic_stripped - if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable: - _Entry = self.SymbolTable[type_str] - if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: - resolved_str = self._resolve_typedef(type_str) - if resolved_str != type_str: - return self._type_str_to_llvm(resolved_str, IsPtr) - if hasattr(_Entry, 'BaseType') and _Entry.BaseType: - from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: - resolved = self._resolve_ctype_to_str(_Entry) - if resolved: - return self._type_str_to_llvm(resolved, IsPtr) - if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: - if type_str in self.structs: - return self.structs[type_str] - if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'BaseType'): - from lib.includes import t as _t - if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - for ClassName in self.structs: - if type_str == ClassName: - if IsPtr: - return ir.PointerType(self.structs[ClassName]) - return self.structs[ClassName] - if '.' in type_str and not type_str.startswith('%'): - last_part = type_str.split('.')[-1] - basic_last = self._basic_type_to_llvm(last_part) - if basic_last is not None: - if IsPtr and not isinstance(basic_last, ir.VoidType): - return ir.PointerType(basic_last) - return basic_last - if hasattr(self, 'SymbolTable') and self.SymbolTable and last_part in self.SymbolTable: - _Entry = self.SymbolTable[last_part] - if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: - resolved_str = self._resolve_typedef(last_part) - if resolved_str != last_part: - return self._type_str_to_llvm(resolved_str, IsPtr) - if hasattr(_Entry, 'BaseType') and _Entry.BaseType: - from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: - resolved = self._resolve_ctype_to_str(_Entry) - if resolved: - return self._type_str_to_llvm(resolved, IsPtr) - if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: - if last_part in self.structs: - return self.structs[last_part] - if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'BaseType'): - from lib.includes import t as _t - if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if last_part in self.structs: - if IsPtr: - return ir.PointerType(self.structs[last_part]) - return self.structs[last_part] - placeholder = self._get_or_create_struct(last_part) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('struct '): - stripped = type_str[7:].strip().replace(' *', '').replace('*', '') - if stripped in self.structs: - if IsPtr: - return ir.PointerType(self.structs[stripped]) - return self.structs[stripped] - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - placeholder = self._get_or_create_struct(stripped) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('%struct.'): - stripped = type_str[8:].strip().replace(' *', '').replace('*', '') - if stripped in self.structs: - if IsPtr: - return ir.PointerType(self.structs[stripped]) - return self.structs[stripped] - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - placeholder = self._get_or_create_struct(stripped) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('union '): - stripped = type_str[6:].strip() - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - if type_str.endswith('*'): - pointee = self._type_str_to_llvm(type_str[:-1].strip()) - if isinstance(pointee, ir.VoidType): - return ir.PointerType(ir.IntType(8)) - return ir.PointerType(pointee) - result = self._basic_type_to_llvm(type_str) - if result is None: - result = ir.IntType(32) - if IsPtr: - if isinstance(result, ir.VoidType): - result = ir.PointerType(ir.IntType(8)) - elif isinstance(result, ir.PointerType): - pass - else: - result = ir.PointerType(result) - for _ in range(ptr_depth - 1): - result = ir.PointerType(result) - return result - - def _llvm_str_to_ir(self, llvm_str): - _LLVM_IR_TYPES = { - 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), - 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), - 'i128': ir.IntType(128), 'float': ir.FloatType(), 'double': ir.DoubleType(), - 'half': ir.IntType(16), 'fp128': ir.IntType(128), - } - return _LLVM_IR_TYPES.get(llvm_str) - - def _basic_type_to_llvm(self, type_str): - _LLVM_IR_TYPES = { - 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), - 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), - 'i128': ir.IntType(128), 'f32': ir.FloatType(), 'f64': ir.DoubleType(), - 'half': ir.IntType(16), 'fp128': ir.IntType(128), - } - if type_str in _LLVM_IR_TYPES: - return _LLVM_IR_TYPES[type_str] - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(type_str) - if resolved is not None: - ctype_cls, ptr_level = resolved - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str: - base = self._llvm_str_to_ir(llvm_str) - if base is not None: - for _ in range(ptr_level): - if isinstance(base, ir.VoidType): - base = ir.IntType(8).as_pointer() - else: - base = ir.PointerType(base) - return base - cnameres = CTypeRegistry.CNameToClass(type_str) - if cnameres is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) - if llvm_str: - return self._llvm_str_to_ir(llvm_str) - if type_str == '*': - return ir.IntType(8) - if type_str in ('const_', 'const'): - return ir.IntType(8) - return None - - def _is_type_unsigned(self, type_str): - s = type_str.strip() - if s.endswith('*'): - return True - if s.startswith('unsigned'): - return True - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(s) - if resolved is not None: - ctype_cls, _ = resolved - try: - inst = ctype_cls() - if getattr(inst, 'IsSigned', None) is False: - return True - except Exception: - pass - cnameres = CTypeRegistry.CNameToClass(s) - if cnameres is not None: - try: - inst = cnameres() - if getattr(inst, 'IsSigned', None) is False: - return True - except Exception: - pass - return False - - def _record_var_signedness(self, name, type_str_or_bool): - if isinstance(type_str_or_bool, bool): - self.var_signedness[name] = type_str_or_bool - else: - self.var_signedness[name] = self._is_type_unsigned(type_str_or_bool) - - def _is_var_unsigned(self, name): - return self.var_signedness.get(name, False) - - def _check_node_unsigned(self, node): - if isinstance(node, ast.Name): - return self._is_var_unsigned(node.id) - if isinstance(node, ast.BinOp): - return self._check_node_unsigned(node.left) or self._check_node_unsigned(node.right) - if isinstance(node, ast.UnaryOp): - return self._check_node_unsigned(node.operand) - if isinstance(node, ast.Call): - return False - if isinstance(node, ast.Subscript): - return self._check_node_unsigned(node.value) - if isinstance(node, ast.Attribute): - return self._check_node_unsigned(node.value) - return False - - def _get_align(self, llvm_type): - if isinstance(llvm_type, ir.IntType): - return max(1, llvm_type.width // 8) - if isinstance(llvm_type, ir.FloatType): - return 4 - if isinstance(llvm_type, ir.DoubleType): - return 8 - if isinstance(llvm_type, ir.PointerType): - return self.ptr_size - if isinstance(llvm_type, ir.ArrayType): - return self._get_align(llvm_type.element) - if isinstance(llvm_type, ir.LiteralStructType): - return max((self._get_align(f) for f in llvm_type.elements), default=1) - if isinstance(llvm_type, ir.IdentifiedStructType): - if llvm_type.elements is None or len(llvm_type.elements) == 0: - return self.ptr_size # opaque struct, assume pointer alignment - return max((self._get_align(f) for f in llvm_type.elements), default=1) - if isinstance(llvm_type, ir.VoidType): - return 0 - return 4 - - def _get_struct_size(self, llvm_type): - if isinstance(llvm_type, ir.IntType): - return max(1, llvm_type.width // 8) - if isinstance(llvm_type, ir.FloatType): - return 4 - if isinstance(llvm_type, ir.DoubleType): - return 8 - if isinstance(llvm_type, ir.PointerType): - return self.ptr_size - if isinstance(llvm_type, ir.ArrayType): - return self._get_struct_size(llvm_type.element) * llvm_type.count - if isinstance(llvm_type, ir.LiteralStructType): - total = 0 - max_align = 1 - for f in llvm_type.fields: - fa = self._get_align(f) - fs = self._get_struct_size(f) - max_align = max(max_align, fa) - if fa > 1: - total = (total + fa - 1) // fa * fa - total += fs - if max_align > 1: - total = (total + max_align - 1) // max_align * max_align - return total - if isinstance(llvm_type, ir.IdentifiedStructType): - if llvm_type.elements is None or len(llvm_type.elements) == 0: - return self.ptr_size # opaque struct, assume pointer size - total = 0 - max_align = 1 - for f in llvm_type.elements: - fa = self._get_align(f) - fs = self._get_struct_size(f) - max_align = max(max_align, fa) - if fa > 1: - total = (total + fa - 1) // fa * fa - total += fs - if max_align > 1: - total = (total + max_align - 1) // max_align * max_align - return total - return 4 - - @staticmethod - def _strip_unnecessary_quotes(ir_str): - def _unquote(m): - prefix = m.group(1) - name = m.group(2) - if '.' in name: - return m.group(0) - if re.match(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$', name): - return prefix + name - return m.group(0) - return re.sub(r'([@%])"([^"]+)"', _unquote, ir_str) - - def finalize(self): - self._set_Vtable_initializers() - self._fix_global_var_init() - try: - ir_text = str(self.module) - except TypeError as e: - for func in self.module.functions: - for block in func.blocks: - for instr in block.instructions: - try: - str(instr) - except TypeError as te: - pass - raise - ir_text = self._strip_unnecessary_quotes(ir_text) - struct_defs = [] - struct_names = set() - typedef_names = TYPEDEF_NAMES - for ClassName, struct_type in self.structs.items(): - if isinstance(struct_type, ir.IdentifiedStructType): - sname = struct_type.name - if sname[0].isdigit() or '.' in sname or not sname.replace('_', '').replace('.', '').isalnum(): - sname_ir = f'%"{sname}"' - else: - sname_ir = f'%{sname}' - if struct_type.elements is None or len(struct_type.elements) == 0: - if ClassName not in typedef_names: - struct_names.add(sname) - struct_defs.append(f'{sname_ir} = type opaque') - continue - elems = ', '.join(str(e) for e in struct_type.elements) - if struct_type.packed: - struct_defs.append(f'{sname_ir} = type <{{ {elems} }}>') - else: - struct_defs.append(f'{sname_ir} = type {{ {elems} }}') - struct_names.add(sname) - if struct_defs: - lines = ir_text.split('\n') - filtered = [] - for line in lines: - stripped = line.strip() - skip = False - for name in struct_names: - if name[0].isdigit() or '.' in name or not name.replace('_', '').replace('.', '').isalnum(): - patterns = [f'%"{name}" = type', f'%"{name}"=type', f'%{name} = type', f'%{name}=type'] - else: - patterns = [f'%{name} = type', f'%{name}= type', f'%{name}=type'] - for p in patterns: - if stripped.startswith(p): - skip = True - break - if skip: - break - if not skip: - filtered.append(line) - ir_text = '\n'.join(filtered) - header_end = ir_text.find('\ndefine') - if header_end == -1: - header_end = ir_text.find('\ndeclare') - if header_end == -1: - header_end = ir_text.find('\n@') - if header_end == -1: - header_end = len(ir_text) - insert_pos = ir_text.rfind('\n', 0, header_end) - if insert_pos == -1: - insert_pos = header_end - struct_block = '\n'.join(struct_defs) + '\n' - ir_text = ir_text[:insert_pos + 1] + struct_block + ir_text[insert_pos + 1:] - for name in struct_names: - if name[0].isdigit() or '.' in name: - ir_text = re.sub( - r'%' + re.escape(name) + r'(?=[^a-zA-Z0-9_$\.]|$)', - r'%"' + name + r'"', - ir_text - ) - - return ir_text - - def _collect_classes_and_methods(self, ast_nodes, parent=None): - current_class = None - for node in ast_nodes: - if isinstance(node, str): - continue - node.parent = parent - node_type = type(node).__name__ - if node_type == 'Struct': - if hasattr(node, 'name'): - current_class = node.name - self.class_methods[current_class] = [] - self.class_members[current_class] = [] - if hasattr(node, 'decls') and node.decls: - for decl in node.decls: - if type(decl).__name__ == 'Decl' and hasattr(decl, 'name'): - member_type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32) - self.class_members[current_class].append((decl.name, member_type)) - elif node_type == 'FuncDef': - if current_class and current_class in self.class_methods: - MethodName = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method' - if not MethodName.startswith(f"{current_class}."): - MethodName = f"{current_class}.{MethodName}" - self.class_methods[current_class].append(MethodName) - if hasattr(node, 'body') and isinstance(node.body, list): - self._collect_classes_and_methods(node.body, parent=node) - elif hasattr(node, 'BlockItems') and node.BlockItems: - self._collect_classes_and_methods(node.BlockItems, parent=node) - - def _generate_structs(self): - all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) - - preserved_structs = {} - for name, st in self.structs.items(): - if name not in all_classes: - preserved_structs[name] = st - elif isinstance(st, ir.IdentifiedStructType): - preserved_structs[name] = st - - self.structs.clear() - - for name, st in preserved_structs.items(): - self.structs[name] = st - - # Step 1: 先为所有类创建空的 struct,确保后面可以正确引用 - all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) - for ClassName in all_classes: - is_packed = ClassName in self.class_packed - if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: - Entry = self.SymbolTable[ClassName] - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: - continue - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: - if not getattr(Entry, 'IsRenum', False): - continue - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - if hasattr(Entry, 'BaseType') and Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)): - import lib.includes.t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)): - continue - if ClassName in self.structs: - if is_packed: - self.structs[ClassName].packed = True - continue - mangled_name = self._mangle_name(ClassName) - struct_type = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed) - self.structs[ClassName] = struct_type - - # Step 2: 解析跨模块的成员类型 - for ClassName, annotations in self.class_member_annotations.items(): - if ClassName not in self.class_members: - continue - for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): - if member_name in annotations: - annotation = annotations[member_name] - ResolvedType = None - - if isinstance(annotation, ast.Attribute): - ClassTypeName = annotation.attr - if ClassTypeName in self.structs: - ResolvedType = self.structs[ClassTypeName] - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - left = annotation.left - if isinstance(left, ast.Attribute): - ClassTypeName = left.attr - if ClassTypeName in self.structs: - ResolvedType = self.structs[ClassTypeName] - - if ResolvedType: - self.class_members[ClassName][i] = (member_name, ResolvedType) - - struct_name_map = {} - for struct_name, struct in self.structs.items(): - try: - struct_name_map[struct.name] = struct - except AssertionError: - struct_name_map[struct_name] = struct - orig = getattr(struct, '_original_name', None) - if orig: - struct_name_map[orig] = struct - - # Step 3: 更新成员类型,确保使用正确的 mangled struct 引用 - for ClassName in all_classes: - if ClassName not in self.class_members: - continue - for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): - if isinstance(member_type, ir.PointerType): - pointee = member_type.pointee - if isinstance(pointee, ir.IdentifiedStructType): - try: - pname = pointee.name - except AssertionError: - pname = None - struct = struct_name_map.get(pname) if pname else None - if struct is None: - orig = getattr(pointee, '_original_name', None) - struct = struct_name_map.get(orig) if orig else None - if struct is not None: - self.class_members[ClassName][i] = (member_name, ir.PointerType(struct)) - else: - raw_name = pname or '' - if raw_name.startswith('struct.'): - raw_name = raw_name[7:] - new_struct = self._get_or_create_struct(raw_name) - self.class_members[ClassName][i] = (member_name, ir.PointerType(new_struct)) - elif isinstance(member_type, ir.IdentifiedStructType): - try: - mname = member_type.name - except AssertionError: - mname = None - struct = struct_name_map.get(mname) if mname else None - if struct is None: - orig = getattr(member_type, '_original_name', None) - struct = struct_name_map.get(orig) if orig else None - if struct is not None: - self.class_members[ClassName][i] = (member_name, struct) - else: - raw_name = mname or '' - if raw_name.startswith('struct.'): - raw_name = raw_name[7:] - new_struct = self._get_or_create_struct(raw_name) - self.class_members[ClassName][i] = (member_name, new_struct) - - # Step 4: 创建最终的 structs 并设置正确的成员类型 - for ClassName in all_classes: - if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: - Entry = self.SymbolTable[ClassName] - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: - continue - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: - if not getattr(Entry, 'IsRenum', False): - continue - existing_st = self.structs.get(ClassName) - if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0: - # 即使 struct 已有元素,也需要修正 packed 属性 - if ClassName in self.class_packed and not existing_st.packed: - existing_st.packed = True - continue - has_vtable = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes - if not has_vtable: - p = self.class_parent.get(ClassName) - while p: - if p in self.class_vtable or p in self._cross_module_vtable_classes: - has_vtable = True - self.class_vtable.add(ClassName) - break - p = self.class_parent.get(p) - has_bitfield = ClassName in self.class_member_bitfields and any( - self.class_member_bitfields[ClassName].get(name, 0) > 0 - for name, _ in self.class_members.get(ClassName, []) - ) - all_members = self.class_members.get(ClassName, []) - all_bitfield = all( - self.class_member_bitfields.get(ClassName, {}).get(name, 0) > 0 - for name, _ in all_members - ) if all_members else False - - mangled_name = self._mangle_name(ClassName) - - if has_bitfield and all_bitfield: - total_bits = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0) - for name, _ in all_members) - if total_bits <= 8: - storage_type = ir.IntType(8) - elif total_bits <= 16: - storage_type = ir.IntType(16) - elif total_bits <= 32: - storage_type = ir.IntType(32) - else: - storage_type = ir.IntType(64) - member_types = [storage_type] - bitfield_offsets = {} - current_bit_offset = 0 - for name, _ in all_members: - bit_width = self.class_member_bitfields.get(ClassName, {}).get(name, 0) - bitfield_offsets[name] = current_bit_offset - current_bit_offset += bit_width - self.class_member_bitoffsets[ClassName] = bitfield_offsets - else: - member_types = [] - if has_vtable: - member_types.append(ir.PointerType(ir.IntType(8))) - if ClassName in self.class_members: - for _, member_type in self.class_members[ClassName]: - if member_type is None: - member_type = ir.IntType(32) - member_types.append(member_type) - else: - member_types = [ir.IntType(8)] - - # 获取之前创建的 struct 并设置成员 - struct_type = self.structs[ClassName] - if ClassName in self.class_packed: - struct_type.packed = True - # 只在未设置 body 时设置,避免重复定义错误 - if struct_type.elements is None: - struct_type.set_body(*member_types) - - def _create_Vtable_globals(self): - for ClassName, methods in self.class_methods.items(): - if ClassName in self.Vtables: - continue - if not methods: - continue - if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes: - continue - VtableType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) - Vtable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable")) - Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) - Vtable.linkage = 'internal' - self.Vtables[ClassName] = Vtable - - def _fix_global_var_init(self): - for gv_name, gv in list(self.module.globals.items()): - if not isinstance(gv, ir.GlobalVariable): - continue - if gv.linkage in ('external', 'extern_weak'): - continue - needs_fix = False - if gv.initializer is None: - needs_fix = True - elif hasattr(gv.initializer, 'constant') and isinstance(gv.initializer.constant, _Undefined): - needs_fix = True - elif isinstance(gv.initializer, ir.Constant): - if isinstance(gv.initializer.constant, list): - if any(hasattr(c, 'constant') and isinstance(c.constant, _Undefined) for c in gv.initializer.constant): - needs_fix = True - if not needs_fix: - continue - gv.initializer = ir.Constant(gv.value_type, None) - if gv_name.startswith('str_const_') or gv_name.endswith('_Vtable') or gv_name.endswith('_str'): - gv.linkage = 'internal' - - def _zero_value_for_type(self, var_type): - if isinstance(var_type, ir.IntType): - return ir.Constant(var_type, 0) - elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(var_type, 0.0) - elif isinstance(var_type, ir.PointerType): - return ir.Constant(var_type, None) - elif isinstance(var_type, ir.ArrayType): - elem_zv = self._zero_value_for_type(var_type.element) - if elem_zv is None: - return None - return ir.Constant(var_type, [elem_zv] * var_type.count) - elif isinstance(var_type, ir.BaseStructType): - if var_type.elements is not None and len(var_type.elements) > 0: - elem_zvs = [self._zero_value_for_type(m) for m in var_type.elements] - if any(zv is None for zv in elem_zvs): - return None - return ir.Constant(var_type, elem_zvs) - return None - return None - - def _set_Vtable_initializers(self): - for ClassName, methods in self.class_methods.items(): - if ClassName not in self.Vtables: - continue - if not methods: - continue - struct_type = self.structs.get(ClassName) - if not struct_type: - continue - Vtable = self.Vtables[ClassName] - Vtable_entries = [] - for MethodName in methods: - short_name = MethodName.split('.')[-1] if '.' in MethodName else MethodName - full_MethodName = f"{ClassName}.{short_name}" - func = None - if full_MethodName in self.functions: - func = self.functions[full_MethodName] - if func is None: - parent_cls = self.class_parent.get(ClassName) - while parent_cls: - parent_full = f"{parent_cls}.{short_name}" - if parent_full in self.functions: - func = self.functions[parent_full] - break - parent_cls = self.class_parent.get(parent_cls) - if func is None: - Vtable_entries.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) - continue - Vtable_entries.append(func.bitcast(ir.PointerType(ir.IntType(8)))) - Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries) - - def _adjust_args(self, args, func): - adjusted = [] - for i, (arg, param) in enumerate(zip(args, func.args)): - if arg.type != param.type: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"load_arg_{i}")) - continue - try: - if isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): - if isinstance(param.type.pointee, ir.IntType) and param.type.pointee.width == 8 and arg.type.width == 8: - # 当参数是 i8(字符值)而函数期望 i8*(字符串指针)时 - # 为字符值分配内存,创建 null-terminated 字符串 - tmp = self._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"char2str_arg_{i}") - zero = ir.Constant(ir.IntType(32), 0) - char_ptr = self.builder.gep(tmp, [zero, zero], name=f"char2str_ptr_{i}") - self._store(arg, char_ptr) - null_ptr = self.builder.gep(tmp, [zero, ir.Constant(ir.IntType(32), 1)], name=f"char2str_null_{i}") - self._store(ir.Constant(ir.IntType(8), 0), null_ptr) - adjusted.append(char_ptr) - else: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 当参数是指针而函数期望整数时,使用 ptrtoint - adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) - else: - if arg.type.width < 32: - arg = self.builder.zext(arg, ir.IntType(32), name=f"zext_arg_{i}") - adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 当参数是指针而函数期望整数时,使用 ptrtoint - adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.PointerType): - if isinstance(arg.type.pointee, ir.PointerType) and isinstance(param.type.pointee, ir.IntType): - loaded = self._load(arg, name=f"load_arg_{i}") - adjusted.append(loaded) - elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): - zero = ir.Constant(ir.IntType(32), 0) - elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") - if elem_ptr.type != param.type: - adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) - else: - adjusted.append(elem_ptr) - elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, ir.PointerType): - zero = ir.Constant(ir.IntType(32), 0) - elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") - if elem_ptr.type != param.type: - adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) - else: - adjusted.append(elem_ptr) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - else: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"load_arg_{i}")) - elif isinstance(arg.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - tmp = self._alloca(param.type, name=f"temp_arg_{i}") - loaded = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") - loaded_val = self._load(loaded, name=f"load_arg_{i}") - self._store(loaded_val, tmp) - adjusted.append(self._load(tmp, name=f"reload_arg_{i}")) - else: - tmp = self._alloca(param.type, name=f"temp_arg_{i}") - cast_ptr = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") - loaded_val = self._load(cast_ptr, name=f"load_arg_{i}") - self._store(loaded_val, tmp) - adjusted.append(self._load(tmp, name=f"reload_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: - adjusted.append(self._load(arg, name=f"load_arg_{i}")) - elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: - tmp = self._alloca(arg.type, name=f"temp_arg_{i}") - self._store(arg, tmp) - adjusted.append(tmp) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.IntType): - if arg.type.width < param.type.width: - # 整数扩展:使用 sext(符号扩展)以正确处理负数 - adjusted.append(self.builder.sext(arg, param.type, name=f"sext_arg_{i}")) - else: - adjusted.append(self.builder.trunc(arg, param.type, name=f"trunc_arg_{i}")) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): - if isinstance(arg.type, ir.DoubleType) and isinstance(param.type, ir.FloatType): - adjusted.append(self.builder.fptrunc(arg, param.type, name=f"fptrunc_arg_{i}")) - elif isinstance(arg.type, ir.FloatType) and isinstance(param.type, ir.DoubleType): - adjusted.append(self.builder.fpext(arg, param.type, name=f"fpext_arg_{i}")) - else: - adjusted.append(arg) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, ir.IntType): - adjusted.append(self.builder.fptosi(arg, param.type, name=f"fptosi_arg_{i}")) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): - adjusted.append(self.builder.sitofp(arg, param.type, name=f"sitofp_arg_{i}")) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): - # 整数转指针:inttoptr - if arg.type.width < 64: - i64_val = self.builder.sext(arg, ir.IntType(64), name=f"sext_arg_{i}") - adjusted.append(self.builder.inttoptr(i64_val, param.type, name=f"inttoptr_arg_{i}")) - else: - adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 指针转整数:ptrtoint - i64_val = self.builder.ptrtoint(arg, ir.IntType(64), name=f"ptrtoint_arg_{i}") - if i64_val.type.width > param.type.width: - adjusted.append(self.builder.trunc(i64_val, param.type, name=f"trunc_arg_{i}")) - elif i64_val.type.width < param.type.width: - adjusted.append(self.builder.sext(i64_val, param.type, name=f"sext_arg_{i}")) - else: - adjusted.append(i64_val) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - except Exception: # 参数类型调整失败时使用简化回退逻辑 - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"load_arg_{i}")) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: - adjusted.append(self._load(arg, name=f"load_arg_{i}")) - elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: - tmp = self._alloca(arg.type, name=f"temp_arg_{i}") - self._store(arg, tmp) - adjusted.append(tmp) - else: - adjusted.append(arg) - else: - adjusted.append(arg) - while len(adjusted) < len(func.args): - missing_idx = len(adjusted) - param = func.args[missing_idx] - param_type = param.type if hasattr(param, 'type') else param - if isinstance(param_type, ir.PointerType): - adjusted.append(ir.Constant(param_type, None)) - elif isinstance(param_type, ir.IntType): - adjusted.append(ir.Constant(param_type, 0)) - elif isinstance(param_type, (ir.FloatType, ir.DoubleType)): - adjusted.append(ir.Constant(param_type, 0.0)) - else: - adjusted.append(ir.Constant(ir.IntType(32), 0)) - if func.type.pointee.var_arg: - for i in range(len(func.args), len(args)): - arg = args[i] - adjusted.append(arg) - return adjusted - - def _get_member_offset(self, field_name, ClassName=None): - has_vtable = ClassName and (ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes) - base = 1 if has_vtable else 0 - if ClassName and ClassName in self.structs: - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: - if ClassName in self.class_members: - expected_fields = len(self.class_members[ClassName]) - actual_elements = len(struct_type.elements) - if base > 0 and actual_elements == expected_fields: - base = 0 - if ClassName and ClassName in self.class_members: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - short_name = ClassName.split('.')[-1] if ClassName and '.' in ClassName else None - if short_name and short_name in self.class_members: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - if ClassName and field_name: - if ClassName not in self.class_members or field_name not in [n for n, _ in self.class_members.get(ClassName, [])]: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): - sha1_map = getattr(self, 'module_sha1_map', {}) - for mod_name, mod_sha1 in sha1_map.items(): - stub_name = f"{mod_sha1}.stub.ll" - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, stub_name, self) - if ClassName in self.class_members and len(self.class_members[ClassName]) > 0: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - break - if short_name: - for mod_name, mod_sha1 in sha1_map.items(): - stub_name = f"{mod_sha1}.stub.ll" - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_name, stub_name, self) - if short_name in self.class_members and len(self.class_members[short_name]) > 0: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - break - if ClassName and field_name: - for cn_key in self.class_members: - if cn_key == ClassName or cn_key.endswith(f'.{ClassName}') or (short_name and (cn_key == short_name or cn_key.endswith(f'.{short_name}'))): - for i, (name, _) in enumerate(self.class_members[cn_key]): - if name == field_name: - return base + i - if ClassName and ClassName in self.structs: - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: - for cn_key, members in self.class_members.items(): - if cn_key == short_name or (short_name and cn_key.endswith(f'.{short_name}')): - for i, (name, _) in enumerate(members): - if name == field_name and i < len(struct_type.elements): - return i - break - else: - if short_name: - for cn_key, members in self.class_members.items(): - sn = cn_key.split('.')[-1] if '.' in cn_key else cn_key - if sn == short_name: - for i, (name, _) in enumerate(members): - if name == field_name and i < len(struct_type.elements): - return i - break - if ClassName and field_name and ClassName not in self.class_members: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): - for temp_dir_candidate in [getattr(self, '_temp_dir', None)]: - if temp_dir_candidate and os.path.isdir(temp_dir_candidate): - for pyi_file in os.listdir(temp_dir_candidate): - if pyi_file.endswith('.pyi'): - stub_name = pyi_file.replace('.pyi', '.stub.ll') - short_cn = short_name if short_name else ClassName - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_cn, stub_name, self) - if short_cn in self.class_members and len(self.class_members[short_cn]) > 0: - for i, (name, _) in enumerate(self.class_members[short_cn]): - if name == field_name: - return base + i - break - if ClassName and ClassName in self.structs and (ClassName not in self.class_members or len(self.class_members.get(ClassName, [])) == 0): - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ClassHandler'): - class_handler = self._Trans.ClassHandler - if hasattr(self, '_current_tree') and self._current_tree: - for node in ast.iter_child_nodes(self._current_tree): - if isinstance(node, ast.ClassDef) and (node.name == ClassName or node.name == short_name): - if node.name not in self.class_members: - self.class_members[node.name] = [] - if len(self.class_members[node.name]) == 0: - class_handler._PreRegisterClassMembers(node, self) - if ClassName in self.class_members: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - if short_name and short_name in self.class_members: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - break - return None - - def _resolve_class_for_var(self, var_name): - for ClassName in self.class_methods: - if var_name == ClassName or var_name.startswith(f"__with_{ClassName}_"): - return ClassName - if var_name in self.variables: - var = self.variables[var_name] - if isinstance(var.type, ir.PointerType): - for ClassName, struct_type in self.structs.items(): - if var.type.pointee == struct_type: - return ClassName - if isinstance(var.type.pointee, ir.PointerType) and var.type.pointee.pointee == struct_type: - return ClassName - return None - - def _GetOrCreateFunc(self, FuncName, ArgTypes): - mangled_name = self._mangle_func_name(FuncName) - if mangled_name in self.functions: - return self.functions[mangled_name] - FuncType = self._InferFuncTypeForCall(FuncName, ArgTypes) - try: - func = ir.Function(self.module, FuncType, name=mangled_name) - except Exception: # 函数名冲突时添加前缀重试 - func = ir.Function(self.module, FuncType, name=f"_{mangled_name}") - self.functions[mangled_name] = func - return func - - def _resolve_method_class(self, MethodName): - for ClassName, methods in self.class_methods.items(): - if MethodName in methods: - return ClassName - full_name = f"{ClassName}.{MethodName}" - if full_name in methods: - return ClassName - return None - - def _get_va_start_intrinsic(self): - if 'llvm.va_start' in self.functions: - return self.functions['llvm.va_start'] - ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func = ir.Function(self.module, ftype, name='llvm.va_start') - self.functions['llvm.va_start'] = func - return func - - def _get_va_end_intrinsic(self): - if 'llvm.va_end' in self.functions: - return self.functions['llvm.va_end'] - ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func = ir.Function(self.module, ftype, name='llvm.va_end') - self.functions['llvm.va_end'] = func - return func - - def emit_va_start(self, va_list_ptr): - if not self.builder: - return None - func = self._get_va_start_intrinsic() - i8ptr_type = ir.IntType(8).as_pointer() - if va_list_ptr.type == i8ptr_type: - self.builder.call(func, [va_list_ptr]) - else: - ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") - self.builder.call(func, [ptr]) - return None - - def _emit_stack_align(self, alignment=16): - if not self.builder: - return None - void = ir.VoidType() - asm_type = ir.FunctionType(void, []) - mask = -alignment - intel_asm = f"and rsp, {mask}" - asm_str = _intel_to_att(intel_asm) - asm_func = ir.InlineAsm(asm_type, asm_str, "~{dirflag},~{fpsr},~{flags},~{rsp}", side_effect=True) - self.builder.call(asm_func, [], name="align_stack") - return None - - def emit_va_end(self, va_list_ptr): - if not self.builder: - return None - func = self._get_va_end_intrinsic() - i8ptr_type = ir.IntType(8).as_pointer() - if va_list_ptr.type == i8ptr_type: - self.builder.call(func, [va_list_ptr]) - else: - ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") - self.builder.call(func, [ptr]) - return None - - def emit_va_arg(self, va_list_ptr, arg_type): - if not self.builder: - return self._zero_const(arg_type) - if not hasattr(self, '_va_arg_counter'): - self._va_arg_counter = 0 - self._va_arg_counter += 1 - import sys - is_x86_64 = sys.platform in ('win32', 'win64', 'windows', 'linux', 'linux2', 'darwin') - if is_x86_64: - if isinstance(arg_type, ir.PointerType): - va_arg_type = ir.IntType(64) - elif isinstance(arg_type, (ir.FloatType, ir.DoubleType)): - va_arg_type = ir.DoubleType() - elif isinstance(arg_type, ir.IntType) and arg_type.width < 64: - va_arg_type = ir.IntType(64) - else: - va_arg_type = arg_type - instr = VaArgInstruction(self.builder.block, va_arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') - self.builder._insert(instr) - if va_arg_type != arg_type: - if isinstance(arg_type, ir.PointerType): - result = self.builder.inttoptr(instr, arg_type, name=f'va_arg_ptr_{self._va_arg_counter}') - elif isinstance(arg_type, ir.FloatType): - result = self.builder.fptrunc(instr, arg_type, name=f'va_arg_fptrunc_{self._va_arg_counter}') - else: - result = self.builder.trunc(instr, arg_type, name=f'va_arg_trunc_{self._va_arg_counter}') - else: - result = instr - return result - else: - if isinstance(arg_type, ir.IntType) and arg_type.width < 64: - arg_type = ir.IntType(64) - instr = VaArgInstruction(self.builder.block, arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') - self.builder._insert(instr) - return instr - - def _infer_return_type(self, FuncName): - if FuncName in self.functions: - return self.functions[FuncName].type.pointee.return_type - if FuncName in self.known_return_types: - return self.known_return_types[FuncName] - for ClassName, methods in self.class_methods.items(): - for method in methods: - if FuncName == method: - return ir.VoidType() - return ir.IntType(32) - - def _InferFuncTypeForCall(self, FuncName, ArgTypes): - return_type = self._infer_return_type(FuncName) - if not ArgTypes: - for ClassName, methods in self.class_methods.items(): - if FuncName in methods: - if ClassName in self.structs: - ArgTypes = [ir.PointerType(self.structs[ClassName])] - else: - ArgTypes = [ir.PointerType(ir.LiteralStructType([ir.PointerType(ir.IntType(8)), ir.IntType(32)]))] - break - else: - ArgTypes = [ir.IntType(32)] - return ir.FunctionType(return_type, ArgTypes) - - def _zero_const(self, typ): - if isinstance(typ, ir.PointerType): - return ir.Constant(typ, None) - return ir.Constant(typ, 0) - - def _alloca(self, typ, name='', align=None, size=None): - if align is None: - align = self._get_align(typ) - if size is not None: - instr = self.builder.alloca(typ, size=size, name=name) - else: - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - return instr - - def _alloca_entry(self, typ, name='', align=None): - if align is None: - align = self._get_align(typ) - saved_block = self.builder.block - entry_block = self.func.entry_basic_block - if entry_block.instructions: - first_instr = entry_block.instructions[0] - self.builder.position_before(first_instr) - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - self.builder.position_at_end(saved_block) - else: - self.builder.position_at_start(entry_block) - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - self.builder.position_at_end(saved_block) - return instr - - def _load(self, ptr, name='', align=None): - if align is None: - if isinstance(ptr.type, ir.PointerType): - align = self._get_align(ptr.type.pointee) - else: - align = 0 - if isinstance(ptr.type, ir.PointerType): - pointee_type = ptr.type.pointee - typedef_names = TYPEDEF_NAMES - if isinstance(pointee_type, ir.IdentifiedStructType) and pointee_type.name in typedef_names: - actual_type = ir.IntType(32) - if pointee_type.name in {'BYTE', 'INT8', 'UINT8'}: - actual_type = ir.IntType(8) - elif pointee_type.name in {'WORD', 'INT16', 'UINT16'}: - actual_type = ir.IntType(16) - elif pointee_type.name in {'DWORD', 'INT32', 'UINT32'}: - actual_type = ir.IntType(32) - elif pointee_type.name in {'QWORD', 'INT64', 'UINT64'}: - actual_type = ir.IntType(64) - bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast_load") - return self.builder.load(bitcast_ptr, name=name, align=align) - return self.builder.load(ptr, name=name, align=align) - - def _load_var(self, name): - if name in self._direct_values: - return self._direct_values[name] - if name in self.variables and self.variables[name] is not None: - VarPtr = self.variables[name] - if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return VarPtr - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return VarPtr - return self._load(VarPtr, name=name) - if name in self.global_vars and name in self.module.globals: - GVar = self.module.globals[name] - self.variables[name] = 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 self._load(GVar, name=name) - if name in self.module.globals: - GVar = self.module.globals[name] - self.variables[name] = 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 self._load(GVar, name=name) - return None - - def _store_var(self, name, value): - if name in self._direct_values: - old_val = self._direct_values.pop(name) - if name not in self.variables or self.variables[name] is None: - var = self.builder.alloca(old_val.type, name=name) - self._store(old_val, var) - self.variables[name] = var - if name in self.variables and self.variables[name] is not None: - self._store(value, self.variables[name]) - else: - var = self.builder.alloca(value.type, name=name) - self._store(value, var) - self.variables[name] = var - - def _ensure_alloca(self, name, llvm_type): - if name in self._direct_values: - val = self._direct_values.pop(name) - var = self.builder.alloca(llvm_type, name=name) - self._store(val, var) - self.variables[name] = var - return var - if name in self.variables and self.variables[name] is not None: - return self.variables[name] - var = self.builder.alloca(llvm_type, name=name) - self.variables[name] = var - return var - - def _coerce_value(self, val, target_type): - if val.type == target_type: - return val - typedef_names = TYPEDEF_NAMES - if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in typedef_names: - if isinstance(val.type, ir.IntType): - return val - if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.IntType): - if target_type.width < val.type.width: - return self.builder.trunc(val, target_type, name="trunc_store") - else: - # 使用 sext(符号扩展)以正确处理负数 - return self.builder.sext(val, target_type, name="sext_store") - if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.PointerType): - if isinstance(val, ir.Constant) and val.constant is None: - return ir.Constant(target_type, None) - return self.builder.bitcast(val, target_type, name="ptr_bitcast_store") - if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.IntType): - if val.type.width < 64: - val = self.builder.zext(val, ir.IntType(64), name="zext_ptr_store") - return self.builder.inttoptr(val, target_type, name="int_to_ptr_store") - if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.PointerType): - if isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == target_type.width: - return self.builder.load(val, name="load_ptr_as_int_store") - if target_type.width <= 8 and isinstance(val.type.pointee, ir.IntType): - loaded = self.builder.load(val, name="load_ptr_byte_store") - if loaded.type != target_type: - if isinstance(loaded.type, ir.IntType) and isinstance(target_type, ir.IntType): - if target_type.width < loaded.type.width: - return self.builder.trunc(loaded, target_type, name="trunc_ptr_byte_store") - return self.builder.zext(loaded, target_type, name="zext_ptr_byte_store") - return loaded - return self.builder.ptrtoint(val, target_type, name="ptr_to_int_store") - if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType): - return self.builder.fptrunc(val, target_type, name="fptrunc_store") - if isinstance(target_type, ir.DoubleType) and isinstance(val.type, ir.FloatType): - return self.builder.fpext(val, target_type, name="fpext_store") - if isinstance(target_type, ir.IntType) and isinstance(val.type, (ir.FloatType, ir.DoubleType)): - return self.builder.fptosi(val, target_type, name="fptosi_store") - if isinstance(target_type, (ir.FloatType, ir.DoubleType)) and isinstance(val.type, ir.IntType): - return self.builder.sitofp(val, target_type, name="sitofp_store") - if isinstance(target_type, ir.ArrayType) and isinstance(val.type, ir.ArrayType): - if target_type.count == val.type.count and target_type.element == val.type.element: - return val - if (isinstance(target_type.element, ir.IntType) and target_type.element.width == 8 - and isinstance(val.type.element, ir.IntType) and val.type.element.width == 8): - if target_type.count > val.type.count: - padded = list(val.constant) if hasattr(val, 'constant') else [] - if padded and len(padded) == val.type.count: - padded.extend([ir.Constant(ir.IntType(8), 0)] * (target_type.count - val.type.count)) - return ir.Constant(target_type, padded) - elif target_type.count < val.type.count: - trimmed = list(val.constant) if hasattr(val, 'constant') else [] - if trimmed and len(trimmed) == val.type.count: - return ir.Constant(target_type, trimmed[:target_type.count]) - if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType): - if val.type.pointee == target_type: - return self.builder.load(val, name="load_struct_for_store") - if isinstance(val.type.pointee, ir.IdentifiedStructType) and isinstance(target_type, ir.IdentifiedStructType): - if val.type.pointee.name == target_type.name: - loaded = self.builder.load(val, name="load_struct_for_store") - if loaded.type == target_type: - return loaded - return None - - def _store(self, val, ptr, align=None): - if align is None: - if isinstance(ptr.type, ir.PointerType): - align = self._get_align(ptr.type.pointee) - else: - align = 0 - if isinstance(ptr.type, ir.PointerType): - target_type = ptr.type.pointee - typedef_names = TYPEDEF_NAMES - if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in typedef_names: - if isinstance(val.type, ir.IntType): - actual_type = ir.IntType(32) - if target_type.name in {'BYTE', 'INT8', 'UINT8'}: - actual_type = ir.IntType(8) - elif target_type.name in {'WORD', 'INT16', 'UINT16'}: - actual_type = ir.IntType(16) - elif target_type.name in {'DWORD', 'INT32', 'UINT32'}: - actual_type = ir.IntType(32) - elif target_type.name in {'QWORD', 'INT64', 'UINT64'}: - actual_type = ir.IntType(64) - bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast") - if val.type.width != actual_type.width: - if val.type.width > actual_type.width: - val = self.builder.trunc(val, actual_type, name="trunc_typedef") - else: - val = self.builder.zext(val, actual_type, name="zext_typedef") - return self.builder.store(val, bitcast_ptr, align=align) - if val.type != target_type: - if isinstance(val, ir.Constant) and val.constant is None: - if isinstance(target_type, ir.PointerType): - val = ir.Constant(target_type, None) - elif isinstance(target_type, ir.IdentifiedStructType): - val = ir.Constant(ir.PointerType(target_type), None) - ptr = self.builder.bitcast(ptr, ir.PointerType(ir.PointerType(target_type)), name="null_struct_ptr_cast") - else: - coerced = self._coerce_value(val, target_type) - if coerced is not None: - val = coerced - else: - src_info = self._get_node_info() - raise TypeError(f"cannot store {val.type} to {ptr.type}: mismatching types{src_info}") - return self.builder.store(val, ptr, align=align) - - def _get_var_ptr(self, name): - if name in self._reg_values: - val = self._reg_values[name] - var = self._alloca(val.type, name=name) - self._store(val, var) - self.variables[name] = var - del self._reg_values[name] - return var - if name in self.variables and self.variables[name] is not None: - return self.variables[name] - return None - - def emit_constant(self, value, type_name='int'): - if type_name == 'int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'uint64_t' or type_name == 'unsigned long long': - return ir.Constant(ir.IntType(64), int(value)) - elif type_name == 'uint32_t' or type_name == 'unsigned int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'uint16_t' or type_name == 'unsigned short': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'uint8_t' or type_name == 'unsigned char': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'int64_t' or type_name == 'long long': - return ir.Constant(ir.IntType(64), int(value)) - elif type_name == 'int32_t' or type_name == 'int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'int16_t' or type_name == 'short': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'int8_t' or type_name == 'char': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'float' or type_name == 'float32_t' or type_name == 'FLOAT32': - return ir.Constant(ir.FloatType(), float(value)) - elif type_name == 'double' or type_name == 'float64_t' or type_name == 'FLOAT64': - return ir.Constant(ir.DoubleType(), float(value)) - elif type_name == 'float16_t' or type_name == 'FLOAT16': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'float8_t' or type_name == 'FLOAT8': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'float128_t' or type_name == 'FLOAT128': - return ir.Constant(ir.IntType(128), int(value)) - elif type_name == 'string': - encoded = value.encode('utf-8') + b'\x00' - str_type = ir.ArrayType(ir.IntType(8), len(encoded)) - str_const = ir.Constant(str_type, bytearray(encoded)) - global_var = ir.GlobalVariable(self.module, str_type, name=f"str_const_{self.string_const_counter}") - self.string_const_counter += 1 - global_var.initializer = str_const - global_var.linkage = 'internal' - return self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8)), name="str") - return ir.Constant(ir.IntType(32), int(value)) - - def emit_binary_op(self, op, left, right, is_unsigned=False): - # 处理指针和整数之间的类型转换 - if isinstance(left.type, ir.PointerType) and isinstance(right.type, ir.IntType): - right = self.builder.zext(right, ir.IntType(64), name="int2ptrint") - if op == '+' or op == 'Add': - return self.builder.gep(left, [right], name="ptr_add") - elif op == '-' or op == 'Sub': - return self.builder.gep(left, [self.builder.neg(right, name="neg")], name="ptr_sub") - if isinstance(left.type, ir.IntType) and isinstance(right.type, ir.PointerType): - left = self.builder.zext(left, ir.IntType(64), name="int2ptrint2") - if op == '+' or op == 'Add': - return self.builder.gep(right, [left], name="ptr_add_rev") - is_float = isinstance(left.type, (ir.FloatType, ir.DoubleType)) or \ - isinstance(right.type, (ir.FloatType, ir.DoubleType)) - if is_float: - if isinstance(left.type, (ir.FloatType, ir.DoubleType)): - ftype = left.type - elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): - ftype = right.type - else: - ftype = ir.DoubleType() - if not isinstance(left.type, (ir.FloatType, ir.DoubleType)): - left = self._to_float(left, ftype) - elif left.type != ftype: - if isinstance(left.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - left = self.builder.fpext(left, ftype, name="fpext_l") - else: - left = self.builder.fptrunc(left, ftype, name="fptrunc_l") - if not isinstance(right.type, (ir.FloatType, ir.DoubleType)): - right = self._to_float(right, ftype) - elif right.type != ftype: - if isinstance(right.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - right = self.builder.fpext(right, ftype, name="fpext_r") - else: - right = self.builder.fptrunc(right, ftype, name="fptrunc_r") - float_ops = { - '+': self.builder.fadd, 'Add': self.builder.fadd, - '-': self.builder.fsub, 'Sub': self.builder.fsub, - '*': self.builder.fmul, 'Mult': self.builder.fmul, - '/': self.builder.fdiv, 'Div': self.builder.fdiv, - '%': self.builder.frem, 'Mod': self.builder.frem, - } - float_cmp_ops = { - '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', - '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', - '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', - } - if op in float_ops: - return float_ops[op](left, right, name=op) - if op in float_cmp_ops: - return self.builder.fcmp_ordered(float_cmp_ops[op], left, right, name=op) - if is_unsigned: - ops = { - '+': self.builder.add, 'Add': self.builder.add, - '-': self.builder.sub, 'Sub': self.builder.sub, - '*': self.builder.mul, 'Mult': self.builder.mul, - '/': self.builder.udiv, 'Div': self.builder.udiv, - '%': self.builder.urem, 'Mod': self.builder.urem, - '//': self.builder.udiv, 'FloorDiv': self.builder.udiv, - } - else: - ops = { - '+': self.builder.add, 'Add': self.builder.add, - '-': self.builder.sub, 'Sub': self.builder.sub, - '*': self.builder.mul, 'Mult': self.builder.mul, - '/': self.builder.sdiv, 'Div': self.builder.sdiv, - '%': self.builder.srem, 'Mod': self.builder.srem, - '//': self.builder.sdiv, 'FloorDiv': self.builder.sdiv, - } - cmp_ops = { - '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', - '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', - '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', - } - logic_ops = { - '&&': self.builder.and_, 'And': self.builder.and_, - '||': self.builder.or_, 'Or': self.builder.or_, - } - if op in ('>>', 'RShift') and not is_unsigned: - if isinstance(left.type, ir.IntType): - if left.type.width == 8: - is_unsigned = True - elif left.type.width == 16: - is_unsigned = True - elif left.type.width == 32: - if hasattr(self, '_last_var_name') and self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) - elif left.type.width == 64: - if hasattr(self, '_last_var_name') and self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) - shift_ops = { - '>>': self.builder.lshr if is_unsigned else self.builder.ashr, - 'RShift': self.builder.lshr if is_unsigned else self.builder.ashr, - '<<': self.builder.shl, 'LShift': self.builder.shl, - } - bit_ops = { - '&': self.builder.and_, - '|': self.builder.or_, - '^': self.builder.xor, - } - if op == '**' or op == 'Pow': - if isinstance(left, ir.Constant) and isinstance(right, ir.Constant): - try: - lv = left.constant - rv = right.constant - if isinstance(lv, int) and isinstance(rv, int) and rv >= 0: - result = lv ** rv - return ir.Constant(left.type, result) - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - if isinstance(left.type, (ir.FloatType, ir.DoubleType)): - ftype = left.type - elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): - ftype = right.type - else: - ftype = ir.DoubleType() - lf = self._to_float(left, ftype) - rf = self._to_float(right, ftype) - powf = self.module.globals.get('llvm.pow.f64') - if not powf: - fnty = ir.FunctionType(ir.DoubleType(), [ir.DoubleType(), ir.DoubleType()]) - powf = ir.Function(self.module, fnty, name='llvm.pow.f64') - if lf.type != ir.DoubleType(): - lf = self.builder.fpext(lf, ir.DoubleType(), name="ext_f64") - if rf.type != ir.DoubleType(): - rf = self.builder.fpext(rf, ir.DoubleType(), name="ext_f64") - result = self.builder.call(powf, [lf, rf], name="pow") - both_int = isinstance(left.type, ir.IntType) and isinstance(right.type, ir.IntType) - right_is_pos_int_const = isinstance(right, ir.Constant) and isinstance(right.constant, int) and right.constant >= 0 - if both_int and right_is_pos_int_const: - return self.builder.fptosi(result, left.type, name="pow2int") - if isinstance(left.type, ir.FloatType): - return self.builder.fptrunc(result, ir.FloatType(), name="pow2f32") - return result - if op in ops: - try: - return ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in shift_ops: - try: - return shift_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in bit_ops: - try: - return bit_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in cmp_ops: - try: - if is_unsigned: - return self.builder.icmp_unsigned(cmp_ops[op], left, right, name=op) - return self.builder.icmp_signed(cmp_ops[op], left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in logic_ops: - try: - return logic_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - return left - - def _to_float(self, val, ftype=None): - if ftype is None: - ftype = ir.DoubleType() - if isinstance(val.type, (ir.FloatType, ir.DoubleType)): - if val.type == ftype: - return val - if isinstance(val.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - return self.builder.fpext(val, ftype, name="fpext") - return self.builder.fptrunc(val, ftype, name="fptrunc") - if isinstance(val.type, ir.IntType): - if val.type.width == 1: - val = self.builder.zext(val, ir.IntType(32), name="bool2i32") - return self.builder.sitofp(val, ftype, name="int2float") - return val - - def emit_return(self, value=None): - if not self.builder or self.builder.block.is_terminated: - return - if value is not None: - self._unregister_local_heap_ptr(value) - self._emit_local_heap_frees() - if hasattr(self, '_variadic_info') and self._variadic_info and self._variadic_info.get('va_start_called'): - va_list_ptr = self._variadic_info['va_list_ptr'] - self.emit_va_end(va_list_ptr) - if value is None: - if self.func and hasattr(self.func, 'ftype'): - ret_type = self.func.ftype.return_type - if isinstance(ret_type, ir.IntType): - self.builder.ret(ir.Constant(ret_type, 0)) - elif isinstance(ret_type, ir.PointerType): - self.builder.ret(ir.Constant(ret_type, None)) - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): - self.builder.ret(ir.Constant(ret_type, 0.0)) - elif isinstance(ret_type, ir.IdentifiedStructType): - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - self.builder.ret(zero_val) - elif isinstance(ret_type, ir.ArrayType): - self.builder.ret(ir.Constant(ret_type, None)) - else: - self.builder.ret_void() - else: - self.builder.ret_void() - else: - if self.func and hasattr(self.func, 'ftype'): - ret_type = self.func.ftype.return_type - if ret_type != value.type: - if isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.PointerType): - if value.type.pointee == ret_type: - value = self._load(value, name="ret_load") - else: - value = self.builder.bitcast(value, ret_type, name="ret_cast") - elif isinstance(value.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): - if isinstance(value.type.pointee, ir.IntType) and isinstance(ret_type, ir.IntType) and value.type.pointee.width == ret_type.width: - value = self._load(value, name="ret_load") - elif isinstance(ret_type, ir.IntType): - value = self.builder.ptrtoint(value, ret_type, name="ret_ptrtoint") - elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType): - value = self._load(value, name="ret_load") - elif isinstance(value.type.pointee, ir.PointerType): - loaded = self._load(value, name="ret_deref") - if loaded.type == ret_type: - value = loaded - elif isinstance(ret_type, ir.IntType): - value = self.builder.ptrtoint(loaded, ret_type, name="ret_ptrtoint") - elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType): - if value.type.width < ret_type.width: - # 有符号值用 sext,无符号值用 zext - is_unsigned = id(value) in self._unsigned_results - if is_unsigned: - value = self.builder.zext(value, ret_type, name="ret_zext") - else: - value = self.builder.sext(value, ret_type, name="ret_sext") - elif value.type.width > ret_type.width: - value = self.builder.trunc(value, ret_type, name="ret_trunc") - elif isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.IntType): - value = self.builder.inttoptr(value, ret_type, name="ret_inttoptr") - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, ir.IntType): - value = self.builder.sitofp(value, ret_type, name="ret_int2float") - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, (ir.FloatType, ir.DoubleType)): - if ret_type != value.type: - value = self.builder.fpext(value, ret_type, name="ret_fpext") - self.builder.ret(value) - - def _emit_printf(self, args, unsigned_flags=None, sep=" ", end="\n"): - if not args: - return None - if unsigned_flags is None: - unsigned_flags = [] - format_str = "" - cast_args = [] - for i, arg in enumerate(args): - is_u = i < len(unsigned_flags) and unsigned_flags[i] - if isinstance(arg.type, ir.IntType): - if arg.type.width == 8: - format_str += "%c" - ext = self.builder.zext(arg, ir.IntType(32), name="char2int") - cast_args.append(ext) - elif arg.type.width == 64: - format_str += "%llu" if is_u else "%lld" - cast_args.append(arg) - else: - format_str += "%u" if is_u else "%d" - cast_args.append(arg) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(arg) - elif isinstance(arg.type, ir.PointerType): - if isinstance(arg.type.pointee, ir.IntType) and arg.type.pointee.width == 8: - format_str += "%s" - cast_args.append(arg) - else: - format_str += "%d" - int_val = self.builder.ptrtoint(arg, ir.IntType(64), name="ptr2int") - trunc_val = self.builder.trunc(int_val, ir.IntType(32), name="trunc") - cast_args.append(trunc_val) - else: - format_str += "%d" - cast_args.append(arg) - if sep is not None and i < len(args) - 1: - format_str += sep - if end is not None: - format_str += end - string_type = ir.ArrayType(ir.IntType(8), len(format_str.encode('utf-8')) + 1) - string_const = ir.Constant(string_type, bytearray(format_str + '\x00', 'utf-8')) - global_var = ir.GlobalVariable(self.module, string_type, name=f"str_const_{self.string_const_counter}") - self.string_const_counter += 1 - global_var.initializer = string_const - global_var.linkage = 'internal' - format_ptr = self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) - call_args = [format_ptr] + cast_args - printf_func = self.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - return self.builder.call(printf_func, call_args, name="call_printf") - - def _get_or_declare_func(self, name, func_type): - import re - for fname, fobj in self.functions.items(): - if fname == name: - return fobj - if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): - return fobj - func_decl = ir.Function(self.module, func_type, name=name) - self.functions[name] = func_decl - return func_decl - - def get_or_declare_c_func(self, name, fallback_type=None): - if name in self.functions: - return self.functions[name] - import re - for fname, fobj in self.functions.items(): - if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): - return fobj - stub_func_type = None - if hasattr(self, '_import_handler_ref') and self._import_handler_ref: - try: - stub_func_type = self._import_handler_ref._LookupStubFuncType(name, self) - except Exception: - pass - if stub_func_type: - func_decl = ir.Function(self.module, stub_func_type, name=name) - self.functions[name] = func_decl - return func_decl - if fallback_type is not None: - func_decl = ir.Function(self.module, fallback_type, name=name) - self.functions[name] = func_decl - return func_decl - return None - - def emit_sizeof(self, type_name): - for class_name, struct_type in self.structs.items(): - if type_name == class_name: - size = self._get_struct_size(struct_type) - if size > 0: - return ir.Constant(ir.IntType(64), size) - return ir.Constant(ir.IntType(64), 4) +# 向后兼容:重新导出常量和辅助类 +__all__ = ['LlvmCodeGenerator', 'VaArgInstruction'] diff --git a/lib/core/SymbolNode.py b/lib/core/SymbolNode.py index 1042448..d32e497 100644 --- a/lib/core/SymbolNode.py +++ b/lib/core/SymbolNode.py @@ -1,207 +1,207 @@ -from __future__ import annotations -from typing import Any, Dict, Optional, TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.Handles.HandlesBase import CTypeInfo - -from lib.includes import t - - -class SymbolNode: - """符号表节点,类似 AST 节点的树形结构 - - attributes 存储 CTypeInfo 对象,不再使用 TypeInfo - """ - - def __init__(self, name: str, NodeType: str, lineno: int = 0, file: str = '', parent: SymbolNode | None = None): - from lib.core.Handles.HandlesBase import CTypeInfo - self.name: str = name - self.type: str = NodeType - self.lineno: int = lineno - self.file: str = file - self.parent: SymbolNode | None = parent - self.children: Dict[str, SymbolNode] = {} - self.attributes: CTypeInfo = CTypeInfo() - self.attributes.Name = name - self.attributes.Lineno = lineno - - def get(self, key: str, default: Any = None) -> Any: - """获取属性值""" - if hasattr(self.attributes, key): - return getattr(self.attributes, key) - return self.attributes._extra.get(key, default) - - def set(self, key: str, value: Any): - """设置属性值""" - if hasattr(self.attributes, key): - attr = getattr(type(self.attributes), key, None) - if isinstance(attr, property) and attr.fset is None: - return - setattr(self.attributes, key, value) - else: - self.attributes._extra[key] = value - - def HasChild(self, name: str) -> bool: - """检查是否有子节点""" - return name in self.children - - def GetChild(self, name: str) -> Optional[SymbolNode]: - """获取子节点""" - return self.children.get(name) - - def AddChild(self, node: SymbolNode): - """添加子节点""" - node.parent = self - self.children[node.name] = node - - def RemoveChild(self, name: str) -> bool: - """删除子节点""" - if name in self.children: - del self.children[name] - return True - return False - - def find(self, path: str, separator: str = '.') -> Optional[SymbolNode]: - """根据路径查找节点,如 'test.ClassA'""" - parts = path.split(separator) - current = self - - for part in parts: - if current.HasChild(part): - current = current.GetChild(part) - else: - return None - - return current - - def ToDict(self) -> Dict[str, Any]: - """转换为字典格式""" - result = { - 'type': self.type, - 'lineno': self.lineno, - 'file': self.file, - **self.attributes.entry - } - - if self.children: - result['children'] = {name: child.ToDict() for name, child in self.children.items()} - - return result - - @classmethod - def FromDict(cls, name: str, data: Dict[str, Any]) -> SymbolNode: - """从字典创建节点(兼容性)""" - node = cls(name=name, NodeType=data.get('type', 'unknown')) - node.lineno = data.get('lineno', 0) - node.file = data.get('file', '') - - for key, value in data.items(): - if key not in ('type', 'lineno', 'file', 'children'): - node.set(key, value) - - if 'children' in data: - for ChildName, ChildData in data['children'].items(): - node.AddChild(cls.FromDict(ChildName, ChildData)) - - return node - - @classmethod - def CreateMember(cls, name: str, TypeName: str | None = None, TypeInfo: 'CTypeInfo | None' = None, IsPtr: bool = False, dims: list[int] | None = None, lineno: int = 0, file: str = '') -> SymbolNode: - """创建成员节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo - node = cls(name=name, NodeType='member', lineno=lineno, file=file) - node.attributes = CTypeInfo() - node.attributes.Name = name - node.attributes.Lineno = lineno - if TypeInfo is not None: - node.attributes = TypeInfo - node.attributes.Name = name - node.attributes.Lineno = lineno - else: - if TypeName is not None: - node.attributes.BaseType = CTypeInfo.CreateFromTypeName(TypeName) - if IsPtr: - node.attributes.PtrCount = 1 - if dims: - node.attributes.ArrayDims = list(dims) - return node - - @classmethod - def CreateClass(cls, name: str, TypeKind: type, members: dict | None = None, lineno: int = 0, file: str = '', IsCpythonObject: bool = False, IsPacked: bool = False) -> SymbolNode: - """创建类节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo - node = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file) - node.attributes = CTypeInfo() - node.attributes.Name = name - node.attributes.Lineno = lineno - node.attributes.IsCpythonObject = IsCpythonObject - node.attributes.IsPacked = IsPacked - if members: - for MemberName, MemberInfo in members.items(): - if isinstance(MemberInfo, CTypeInfo): - node.attributes.Members[MemberName] = MemberInfo - elif isinstance(MemberInfo, dict): - CTypeMember = CTypeInfo() - type_str = MemberInfo.get('type', 'int') - is_ptr = MemberInfo.get('IsPtr', False) - if isinstance(type_str, str): - try: - resolved = CTypeInfo.FromTypeName(type_str) - if resolved and resolved.BaseType: - CTypeMember = resolved - else: - CTypeMember.BaseType = t.CInt() - except Exception: - CTypeMember.BaseType = t.CInt() - else: - CTypeMember.BaseType = t.CInt() - if is_ptr and not CTypeMember.IsPtr: - CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1) - node.attributes.Members[MemberName] = CTypeMember - if TypeKind == 'struct': - node.attributes.IsStruct = True - elif TypeKind == 'enum': - node.attributes.IsEnum = True - elif TypeKind == 'union': - node.attributes.IsUnion = True - elif TypeKind == 'typedef': - node.attributes.IsTypedef = True - elif TypeKind == 'exception': - node.attributes.IsExceptionClass = True - return node - - @classmethod - def CreateTypedef(cls, name: str, OriginalType, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode: - from lib.core.Handles.HandlesBase import CTypeInfo - node = cls(name=name, NodeType='typedef', lineno=lineno, file=file) - node.attributes = CTypeInfo() - node.attributes.Name = name - node.attributes.Lineno = lineno - node.attributes.IsTypedef = True - if isinstance(OriginalType, CTypeInfo): - node.attributes.OriginalType = OriginalType - elif isinstance(OriginalType, str): - node.attributes.OriginalType = CTypeInfo.FromTypeName(OriginalType) if OriginalType else None - else: - node.attributes.OriginalType = OriginalType - return node - - @classmethod - def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode: - """创建匿名类型节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo - NodeType = t.CUnion if IsUnion else t.CStruct - node = cls(name=name, NodeType=NodeType, lineno=lineno, file=file) - node.attributes = CTypeInfo() - node.attributes.Name = name - node.attributes.Lineno = lineno - node.attributes.IsAnonymous = True - if IsUnion: - node.attributes.IsUnion = True - else: - node.attributes.IsStruct = True - return node - - @classmethod - def CreateModule(cls, name: str, lineno: int = 0, file: str = '') -> SymbolNode: - """创建模块节点(工厂函数)""" - return cls(name=name, NodeType='module', lineno=lineno, file=file) +from __future__ import annotations +from typing import Any, Dict, Optional, TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.Handles.HandlesBase import CTypeInfo + +from lib.includes import t + + +class SymbolNode: + """符号表节点,类似 AST 节点的树形结构 + + attributes 存储 CTypeInfo 对象,不再使用 TypeInfo + """ + + def __init__(self, name: str, NodeType: str, lineno: int = 0, file: str = '', parent: SymbolNode | None = None): + from lib.core.Handles.HandlesBase import CTypeInfo + self.name: str = name + self.type: str = NodeType + self.lineno: int = lineno + self.file: str = file + self.parent: SymbolNode | None = parent + self.children: Dict[str, SymbolNode] = {} + self.attributes: CTypeInfo = CTypeInfo() + self.attributes.Name = name + self.attributes.Lineno = lineno + + def get(self, key: str, default: Any = None) -> Any: + """获取属性值""" + if hasattr(self.attributes, key): + return getattr(self.attributes, key) + return self.attributes._extra.get(key, default) + + def set(self, key: str, value: Any): + """设置属性值""" + if hasattr(self.attributes, key): + attr = getattr(type(self.attributes), key, None) + if isinstance(attr, property) and attr.fset is None: + return + setattr(self.attributes, key, value) + else: + self.attributes._extra[key] = value + + def HasChild(self, name: str) -> bool: + """检查是否有子节点""" + return name in self.children + + def GetChild(self, name: str) -> Optional[SymbolNode]: + """获取子节点""" + return self.children.get(name) + + def AddChild(self, node: SymbolNode): + """添加子节点""" + node.parent = self + self.children[node.name] = node + + def RemoveChild(self, name: str) -> bool: + """删除子节点""" + if name in self.children: + del self.children[name] + return True + return False + + def find(self, path: str, separator: str = '.') -> Optional[SymbolNode]: + """根据路径查找节点,如 'test.ClassA'""" + parts = path.split(separator) + current = self + + for part in parts: + if current.HasChild(part): + current = current.GetChild(part) + else: + return None + + return current + + def ToDict(self) -> Dict[str, Any]: + """转换为字典格式""" + result = { + 'type': self.type, + 'lineno': self.lineno, + 'file': self.file, + **self.attributes.entry + } + + if self.children: + result['children'] = {name: child.ToDict() for name, child in self.children.items()} + + return result + + @classmethod + def FromDict(cls, name: str, data: Dict[str, Any]) -> SymbolNode: + """从字典创建节点(兼容性)""" + node = cls(name=name, NodeType=data.get('type', 'unknown')) + node.lineno = data.get('lineno', 0) + node.file = data.get('file', '') + + for key, value in data.items(): + if key not in ('type', 'lineno', 'file', 'children'): + node.set(key, value) + + if 'children' in data: + for ChildName, ChildData in data['children'].items(): + node.AddChild(cls.FromDict(ChildName, ChildData)) + + return node + + @classmethod + def CreateMember(cls, name: str, TypeName: str | None = None, TypeInfo: 'CTypeInfo | None' = None, IsPtr: bool = False, dims: list[int] | None = None, lineno: int = 0, file: str = '') -> SymbolNode: + """创建成员节点(工厂函数)""" + from lib.core.Handles.HandlesBase import CTypeInfo + node = cls(name=name, NodeType='member', lineno=lineno, file=file) + node.attributes = CTypeInfo() + node.attributes.Name = name + node.attributes.Lineno = lineno + if TypeInfo is not None: + node.attributes = TypeInfo + node.attributes.Name = name + node.attributes.Lineno = lineno + else: + if TypeName is not None: + node.attributes.BaseType = CTypeInfo.create_FromTypeName(TypeName) + if IsPtr: + node.attributes.PtrCount = 1 + if dims: + node.attributes.ArrayDims = list(dims) + return node + + @classmethod + def CreateClass(cls, name: str, TypeKind: type, members: dict | None = None, lineno: int = 0, file: str = '', IsCpythonObject: bool = False, IsPacked: bool = False) -> SymbolNode: + """创建类节点(工厂函数)""" + from lib.core.Handles.HandlesBase import CTypeInfo + node = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file) + node.attributes = CTypeInfo() + node.attributes.Name = name + node.attributes.Lineno = lineno + node.attributes.IsCpythonObject = IsCpythonObject + node.attributes.IsPacked = IsPacked + if members: + for MemberName, MemberInfo in members.items(): + if isinstance(MemberInfo, CTypeInfo): + node.attributes.Members[MemberName] = MemberInfo + elif isinstance(MemberInfo, dict): + CTypeMember = CTypeInfo() + type_str = MemberInfo.get('type', 'int') + IsPtr = MemberInfo.get('IsPtr', False) + if isinstance(type_str, str): + try: + resolved = CTypeInfo.FromTypeName(type_str) + if resolved and resolved.BaseType: + CTypeMember = resolved + else: + CTypeMember.BaseType = t.CInt() + except Exception: + CTypeMember.BaseType = t.CInt() + else: + CTypeMember.BaseType = t.CInt() + if IsPtr and not CTypeMember.IsPtr: + CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1) + node.attributes.Members[MemberName] = CTypeMember + if TypeKind == 'struct': + node.attributes.is_struct = True + elif TypeKind == 'enum': + node.attributes.IsEnum = True + elif TypeKind == 'union': + node.attributes.IsUnion = True + elif TypeKind == 'typedef': + node.attributes.IsTypedef = True + elif TypeKind == 'exception': + node.attributes.IsExceptionClass = True + return node + + @classmethod + def CreateTypedef(cls, name: str, OriginalType, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode: + from lib.core.Handles.HandlesBase import CTypeInfo + node = cls(name=name, NodeType='typedef', lineno=lineno, file=file) + node.attributes = CTypeInfo() + node.attributes.Name = name + node.attributes.Lineno = lineno + node.attributes.IsTypedef = True + if isinstance(OriginalType, CTypeInfo): + node.attributes.OriginalType = OriginalType + elif isinstance(OriginalType, str): + node.attributes.OriginalType = CTypeInfo.FromTypeName(OriginalType) if OriginalType else None + else: + node.attributes.OriginalType = OriginalType + return node + + @classmethod + def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode: + """创建匿名类型节点(工厂函数)""" + from lib.core.Handles.HandlesBase import CTypeInfo + NodeType = t.CUnion if IsUnion else t.CStruct + node = cls(name=name, NodeType=NodeType, lineno=lineno, file=file) + node.attributes = CTypeInfo() + node.attributes.Name = name + node.attributes.Lineno = lineno + node.attributes.IsAnonymous = True + if IsUnion: + node.attributes.IsUnion = True + else: + node.attributes.is_struct = True + return node + + @classmethod + def CreateModule(cls, name: str, lineno: int = 0, file: str = '') -> SymbolNode: + """创建模块节点(工厂函数)""" + return cls(name=name, NodeType='module', lineno=lineno, file=file) diff --git a/lib/core/SymbolTable.py b/lib/core/SymbolTable.py index f669362..8358bf3 100644 --- a/lib/core/SymbolTable.py +++ b/lib/core/SymbolTable.py @@ -364,12 +364,12 @@ class SymbolTable: OriginalType_kind = 'struct' if OriginalClass in self: OrigTypeInfo = self[OriginalClass] - if OrigTypeInfo.TypeCls in (t.CStruct, t.CEnum, t.CUnion): - if OrigTypeInfo.TypeCls is t.CStruct: + if OrigTypeInfo.type_cls in (t.CStruct, t.CEnum, t.CUnion): + if OrigTypeInfo.type_cls is t.CStruct: OriginalType_kind = 'struct' - elif OrigTypeInfo.TypeCls is t.CEnum: + elif OrigTypeInfo.type_cls is t.CEnum: OriginalType_kind = 'enum' - elif OrigTypeInfo.TypeCls is t.CUnion: + elif OrigTypeInfo.type_cls is t.CUnion: OriginalType_kind = 'union' if prefix == prefixes[0]: @@ -510,7 +510,7 @@ class SymbolTable: except Exception as e: import traceback print(traceback.format_exc()) - print(f"[SymbolTable Error] Failed to load module: {FilePath} - {e}") + print(f"[SymbolTable Error] Failed to Load module: {FilePath} - {e}") return [] def _GetLLVMTypeStr(self, node): diff --git a/lib/core/Translator/AnnotationLoader.py b/lib/core/Translator/AnnotationLoader.py new file mode 100644 index 0000000..91dec3d --- /dev/null +++ b/lib/core/Translator/AnnotationLoader.py @@ -0,0 +1,401 @@ +from __future__ import annotations + +import ast +import sys +import os + +from lib.core.SymbolNode import SymbolNode +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.includes import t + + +class AnnotationLoaderMixin: + """注解模块加载 Mixin + + 提供注解模块/文件的加载与符号表注册能力。 + """ + + def _LoadAnnotationModule(self, ModuleName: str, library_name: str = None, parse_method: str = 'auto'): + """加载注解模块并将 CType 子类注册为 typedef + + 支持两种模式: + 1. AST 模式:如果 ModuleName 是文件路径,解析文件提取 CType + 2. importlib 模式:如果 ModuleName 是模块名,导入模块提取 CType + + Args: + ModuleName: 模块名或文件路径 + library_name: 手动指定的库名称,用于注册到符号表。如果为 None,则从 ModuleName 推断 + parse_method: 解析方法,可选值: + - 'auto': 自动检测(默认) + - 'file': 强制使用 AST 模式(文件路径) + - 'module': 强制使用 importlib 模式(模块名) + """ + import importlib + import sys + import os + + CurrentDir = os.path.dirname(os.path.abspath(__file__)) + ProjectRoot = os.path.dirname(os.path.dirname(os.path.dirname(CurrentDir))) + if ProjectRoot not in sys.path: + sys.path.insert(0, ProjectRoot) + + def register_to_symboltable(module, lib_name: str = None, source_file: str = None): + """将模块中的 CType 子类和 CEnum 类注册到符号表""" + from lib.includes.t import CType, CEnum + count = 0 + for AttrName in dir(module): + attr = getattr(module, AttrName) + # 优先检查是否是 CEnum 子类(枚举) + if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum: + # 注册枚举类型 + EnumNode = SymbolNode.CreateClass( + name=AttrName, + TypeKind='enum', + lineno=0 + ) + EnumNode.set('enum_class', attr) + EnumNode.set('source', 'annotation_module') + EnumNode.set('library_name', lib_name) + EnumNode.set('file', source_file) + self.SymbolTable[AttrName] = EnumNode.attributes + if lib_name: + FullName = f'{lib_name}.{AttrName}' + full_EnumNode = SymbolNode.CreateClass( + name=FullName, + TypeKind='enum', + lineno=0 + ) + full_EnumNode.set('enum_class', attr) + full_EnumNode.set('source', 'annotation_module') + full_EnumNode.set('library_name', lib_name) + full_EnumNode.set('file', source_file) + self.SymbolTable[FullName] = full_EnumNode.attributes + # 枚举成员也需要注册 + for MemberName in dir(attr): + if not MemberName.startswith('_'): + member = getattr(attr, MemberName, None) + if isinstance(member, int): + MemberNode = CTypeInfo() + MemberNode.Name = MemberName + MemberNode.BaseType = t.CEnum(AttrName) + MemberNode.value = member + MemberNode.EnumName = AttrName + MemberNode.library_name = lib_name + MemberNode.IsEnumMember = True + self.SymbolTable[MemberName] = MemberNode + self.SymbolTable[f"{AttrName}.{MemberName}"] = MemberNode + self.SymbolTable[f"{AttrName}_{MemberName}"] = MemberNode + if lib_name: + self.SymbolTable[f"{lib_name}.{AttrName}.{MemberName}"] = MemberNode + self.SymbolTable[f"{lib_name}_{AttrName}_{MemberName}"] = MemberNode + count += 1 + # 检查是否是 CType 子类(typedef 别名) + elif isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: + # 继承 CType 的类是类型别名(typedef),不是结构体 + # 使用手动指定的库名称作为前缀 + if lib_name: + FullName = f'{lib_name}.{AttrName}' + else: + FullName = AttrName + # 同时注册带前缀和不带前缀的名称(都是 typedef 别名) + TypedefNode = SymbolNode.CreateClass( + name=AttrName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', attr().CName) + TypedefNode.set('source', 'annotation_module') + TypedefNode.set('library_name', lib_name) + TypedefNode.set('file', source_file) + self.SymbolTable[AttrName] = TypedefNode.attributes + if lib_name and FullName != AttrName: + FullTypedef_node = SymbolNode.CreateClass( + name=FullName, + TypeKind='typedef', + lineno=0 + ) + FullTypedef_node.set('OriginalType', attr().CName) + FullTypedef_node.set('source', 'annotation_module') + FullTypedef_node.set('library_name', lib_name) + FullTypedef_node.set('file', source_file) + self.SymbolTable[FullName] = FullTypedef_node.attributes + count += 1 + # 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef) + elif AttrName.startswith('_') and len(AttrName) > 1: + PublicName = AttrName[1:] + PublicAttr = getattr(module, PublicName, None) + if PublicAttr is not None and not isinstance(attr, type): + continue + if isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: + if PublicName not in self.SymbolTable: + if lib_name: + FullName = f'{lib_name}.{PublicName}' + else: + FullName = PublicName + TypedefNode = SymbolNode.CreateClass( + name=PublicName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', attr().CName) + TypedefNode.set('source', 'annotation_module') + TypedefNode.set('library_name', lib_name) + TypedefNode.set('file', source_file) + self.SymbolTable[PublicName] = TypedefNode.attributes + if lib_name and FullName != PublicName: + FullTypedef_node = SymbolNode.CreateClass( + name=FullName, + TypeKind='typedef', + lineno=0 + ) + FullTypedef_node.set('OriginalType', attr().CName) + FullTypedef_node.set('source', 'annotation_module') + FullTypedef_node.set('library_name', lib_name) + FullTypedef_node.set('file', source_file) + self.SymbolTable[FullName] = FullTypedef_node.attributes + count += 1 + return count + + # 确定解析方法 + use_file_mode = False + if parse_method == 'file': + use_file_mode = True + elif parse_method == 'module': + use_file_mode = False + else: # auto + use_file_mode = os.path.isfile(ModuleName) + + # 确定库名称 + lib_name = library_name + if lib_name is None: + if use_file_mode: + # 从文件路径推断库名称 + lib_name = os.path.splitext(os.path.basename(ModuleName))[0] + else: + # 模块名就是库名称 + lib_name = ModuleName + + # 根据解析方法加载模块 + if use_file_mode: + # AST 模式:使用 AST 解析文件,不执行代码 + try: + # 临时保存当前的 EmbeddedAssignments 和 TypedefAssignments + saved_embedded = self.EmbeddedAssignments.copy() + saved_typedef = self.TypedefAssignments.copy() + + # 清空 PD 收集(注解文件不应该收集 PD 语句) + self.EmbeddedAssignments = {} + self.TypedefAssignments = {} + + # 直接调用 ParsePythonFile 解析文件提取类型信息 + # 注意:这不会执行任何 Python 代码,只是解析 AST + # UpdateCurrentFile=False 表示不修改 CurrentFile + self.ParsePythonFile(ModuleName, UpdateCurrentFile=False) + + # 恢复主代码文件的 PD 收集 + self.EmbeddedAssignments = saved_embedded + self.TypedefAssignments = saved_typedef + + # 从文件名推断类型前缀(如 test_t -> test_t.xxx) + TypePrefix = lib_name + count = 0 + + # 检查符号表中新增的类型(注解文件解析后的所有 struct 类型) + # 需要检查这些类型是否继承自 CType,如果是则是 typedef 别名 + new_types = [] + for TypeName, TypeInfo in self.SymbolTable.items(): + if TypeInfo.IsStruct: + new_types.append(TypeName) + + # 再次遍历 AST,检测继承自 CType 的类 + try: + with open(ModuleName, 'r', encoding='utf-8') as f: + ann_content = f.read() + ann_tree = ast.parse(ann_content) + for node in ann_tree.body: + if isinstance(node, ast.ClassDef): + ClassName = node.name + # 检查是否有基类 + for base in node.bases: + if isinstance(base, ast.Name) and base.id == 'CType': + # 这个类继承自 CType,是 typedef 别名 + # 更新符号表中的类型为 typedef + if ClassName in self.SymbolTable: + TypedefNode = SymbolNode.CreateClass( + name=ClassName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}')) + TypedefNode.set('source', 'annotation_module') + TypedefNode.set('is_ctype_subclass', True) + self.SymbolTable[ClassName] = TypedefNode.attributes + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析注解文件类型定义失败: {_e}", "Exception") + + # 为所有新增的类型添加库前缀和 source 标记 + for TypeName in new_types: + # 添加带前缀的类型名 + FullName = f'{TypePrefix}.{TypeName}' + TypeInfo = self.SymbolTable[TypeName].copy() + TypeInfo['source'] = 'annotation_module' + TypeInfo['original_name'] = TypeName + self.SymbolTable[FullName] = TypeInfo + count += 1 + + # 再次遍历 AST,查找注解文件中的 typedef 语句(AnnAssign with t.CTypedef) + # 注意:必须在类定义处理完之后再处理 typedef + typedef_annots = [] + # 查找 CEnum 成员变量(AnnAssign with t.CEnum | t.State 或 t.CEnum) + cEnumMembers = [] + try: + with open(ModuleName, 'r', encoding='utf-8') as f: + ann_content = f.read() + ann_tree = ast.parse(ann_content) + for node in ann_tree.body: + # 检测 xxx: t.CEnum 形式的枚举成员变量 + if isinstance(node, ast.AnnAssign): + if isinstance(node.target, ast.Name) and node.annotation: + TargetName = node.target.id + # 检查注解是否是 BinOp (Union) 或直接是 Attribute + IsCenum = False + if isinstance(node.annotation, ast.BinOp): + # 检查是否包含 CEnum + annot_str = ast.dump(node.annotation) + if 'CEnum' in annot_str: + IsCenum = True + elif isinstance(node.annotation, ast.Attribute): + # 直接是 t.CEnum + if node.annotation.attr == t.CEnum.__name__: + IsCenum = True + + if IsCenum: + # 检查值是否是 Constant (枚举成员值) + if node.value and isinstance(node.value, ast.Constant): + value = node.value.value + else: + value = None + cEnumMembers.append((TargetName, value)) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析 CEnum 成员变量失败: {_e}", "Exception") + + # 处理 CEnum 成员变量 + for TargetName, value in cEnumMembers: + # 注册枚举成员 + MemberNode = CTypeInfo() + MemberNode.Name = TargetName + MemberNode.BaseType = t.CEnum(TypePrefix) + MemberNode.value = value + MemberNode.EnumName = TypePrefix + MemberNode.library_name = TypePrefix + MemberNode.IsEnumMember = True + self.SymbolTable[TargetName] = MemberNode + self.SymbolTable[f"{TypePrefix}.{TargetName}"] = MemberNode + self.SymbolTable[f"{TypePrefix}_{TargetName}"] = MemberNode + + try: + with open(ModuleName, 'r', encoding='utf-8') as f: + ann_content = f.read() + ann_tree = ast.parse(ann_content) + for node in ann_tree.body: + # 检测 xxx: t.CTypedef = xxx 形式的 typedef 语句 + if isinstance(node, ast.AnnAssign): + if isinstance(node.target, ast.Name) and node.annotation and node.value: + TargetName = node.target.id + # 检查注解是否是 t.CTypedef + if isinstance(node.annotation, ast.Attribute): + if isinstance(node.annotation.value, ast.Name): + if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': + # 检查值是否是 Name + if isinstance(node.value, ast.Name): + original_name = node.value.id + typedef_annots.append((TargetName, original_name)) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析 typedef 语句失败: {_e}", "Exception") + + # 处理 typedef 注解 + for TargetName, original_name in typedef_annots: + # 检查原始类型是否在符号表中(带前缀或不带前缀) + orig_with_prefix = f'{TypePrefix}.{original_name}' + if orig_with_prefix in self.SymbolTable: + # 添加带前缀的 typedef 别名 + FullTypedef_name = f'{TypePrefix}.{TargetName}' + TypedefNode = SymbolNode.CreateClass( + name=FullTypedef_name, + TypeKind='typedef', + lineno=0 + ) + orig_entry = self.SymbolTable.get(orig_with_prefix, {}) + orig_type_str = f'struct {original_name}' + if isinstance(orig_entry, dict): + if orig_entry.get('type') == 'typedef': + orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}') + elif orig_entry.get('type') == 'enum': + orig_type_str = f'enum {original_name}' + elif hasattr(orig_entry, 'IsTypedef') and orig_entry.IsTypedef: + orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}') + elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum: + orig_type_str = f'enum {original_name}' + TypedefNode.set('OriginalType', orig_type_str) + TypedefNode.set('source', 'annotation_module') + TypedefNode.set('original_name', TargetName) + self.SymbolTable[FullTypedef_name] = TypedefNode.attributes + count += 1 + + self.AnnotationModules.add(lib_name) + return count + except Exception as e: + # 恢复 PD 收集 + self.EmbeddedAssignments = saved_embedded + self.TypedefAssignments = saved_typedef + self.LogWarning(f"AST模式加载注解模块失败: {ModuleName}, 错误: {e}") + return 0 + else: + # importlib 模式:导入模块 + try: + module = importlib.import_module(ModuleName) + count = register_to_symboltable(module, lib_name, None) + self.AnnotationModules.add(lib_name) + return count + except ImportError: + self.LogWarning(f"importlib模式加载注解模块失败: {ModuleName}") + return 0 + except Exception as e: + self.LogWarning(f"加载注解模块失败: {ModuleName}, 错误: {e}") + return 0 + + def _LoadAnnotationFiles(self, FilePaths: list): + """加载多个注解文件并注册到符号表 + + Args: + FilePaths: 文件路径列表,每个元素可以是: + - str: 文件路径或模块名 + - tuple: (path, options) 或 (path, library_name, parse_method) + """ + for item in FilePaths: + if isinstance(item, tuple): + if len(item) >= 3: + path, library_name, parse_method = item[:3] + count = self._loadAnnotationModule(path, library_name, parse_method) + elif len(item) == 2: + path, library_name = item + count = self._loadAnnotationModule(path, library_name, 'auto') + else: + count = self._loadAnnotationModule(item) + else: + count = self._loadAnnotationModule(item) + + # 别名,保持向后兼容 + LoadAnnotationFiles = _LoadAnnotationFiles diff --git a/lib/core/Translator/BaseTranslator.py b/lib/core/Translator/BaseTranslator.py new file mode 100644 index 0000000..8d38afa --- /dev/null +++ b/lib/core/Translator/BaseTranslator.py @@ -0,0 +1,154 @@ +from __future__ import annotations + +from typing import Dict +import sys +import os + +from lib.core.Exportable import Exportable + +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'lib', 'includes')) +from lib.includes import c +from lib.includes import t +from lib.utils.helpers import DetectFileType +from lib.core.Handles import ( + IfHandle, ForHandle, WhileHandle, + AnnAssignHandle, + HandlesTypeMerge, ExprHandle, BodyHandle, + ReturnHandle, AssignHandle, AugAssignHandle, DeleteHandle, + WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle, + ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle, + ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle, + CSpecialCallHandle, TSpecialCallHandle, + ClassHandle, + FunctionHandle, + ImportHandle +) +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.SymbolTable import SymbolTable +from lib.core.SymbolNode import SymbolNode +from lib.constants.config import mode as _ConfigMode +from lib.core.LlvmCodeGenerator import LlvmCodeGenerator + + +def _StrictLog(logger, msg): + """在 strict 模式下记录异常日志""" + if _ConfigMode == "strict": + logger(msg) + + +class BaseTranslatorMixin: + """代码转换器基础 Mixin + + 提供 __init__、日志、调试输出与表达式处理等基础能力。 + """ + + def __init__(self): + self.VarScopes: list[Dict[str, SymbolNode]] = [{}] # 跟踪变量作用域,第一个是全局作用域 + self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型 + self.CurrentCReturnTypes: list[CTypeInfo] = None # 当前函数的 CReturn 类型列表 + self._CurrentCpythonObjectClass: str = None # 当前正在处理的 CPython 对象类名 + self.FunctionDefCache: dict = {} # 函数定义缓存 + self.OriginalLines: list[str] = [] # 原始代码行 + self.Content: str = '' + self.DebugFile: str | None = None # 调试输出文件路径 + self.IsHeader: bool = False # 是否生成头文件(仅处理定义、宏、导入等,忽略函数体) + self.AnnotationModules: set[str] = set() # 注解模块集合,用于识别类型定义模块 + self.Warnings: list[str] = [] # 警告日志 + self._ErrorStack = [] # 错误栈,按顺序收集错误位置 + self.Errors = [] # 错误日志 + self.SliceCount = 0 # 切片计数 + self.SliceInfos = [] # 切片信息列表 + self.SliceLevel = 3 # 切片优化级别 + self.GeneratedTypes = set() # 在当前代码中生成的类型(struct/typedef) + self.EmbeddedAssignments = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量 + self.TypedefAssignments = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量 + self.ChainAssignmentArrays = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...] + self.tree = None # 保存解析后的 AST 树 + self.LibraryPaths = ['.'] # 库搜索路径列表,默认包含当前目录 + self.InClass = False # 是否正在处理 class 定义 + self._UserTypeModules = {} + self._source_module_sig_files = {} + self._global_function_default_args: dict = {} + self.exception_registry: dict = {} + self.exception_parents: dict = {} + self._next_exception_code: int = 100 + + # 导出表 + self.Exportable = Exportable(filename='') + + self.SymbolTable = SymbolTable(self) + self.IfHandler = IfHandle(self) + self.ForHandler = ForHandle(self) + self.WhileHandler = WhileHandle(self) + self.AnnAssignHandler = AnnAssignHandle(self) + self.TypeMergeHandler = HandlesTypeMerge(self) + self.ExprHandler = ExprHandle(self) + self.ExprUtils = ExprUtils(self) + self.ExprOpsHandle = ExprOpsHandle(self) + self.ExprAttrHandle = ExprAttrHandle(self) + self.ExprBuiltinHandle = ExprBuiltinHandle(self) + self.ExprAsmHandle = ExprAsmHandle(self) + self.ExprFormatHandle = ExprFormatHandle(self) + self.ExprLambdaHandle = ExprLambdaHandle(self) + self.ExprCallHandle = ExprCallHandle(self) + self.CSpecialCallHandle = CSpecialCallHandle(self) + self.TSpecialCallHandle = TSpecialCallHandle(self) + self.ClassHandler = ClassHandle(self) + self.FunctionHandler = FunctionHandle(self) + self.ImportHandler = ImportHandle(self) + self.BodyHandler = BodyHandle(self) + self.ReturnHandler = ReturnHandle(self) + self.AssignHandler = AssignHandle(self) + self.AugAssignHandler = AugAssignHandle(self) + self.DeleteHandler = DeleteHandle(self) + self.WithHandler = WithHandle(self) + self.TryHandler = TryHandle(self) + self.AssertHandler = AssertHandle(self) + self.RaiseHandler = RaiseHandle(self) + self.MatchHandler = MatchHandle(self) + + def LogWarning(self, message: str, LineNum: int = None): + """记录警告 + + Args: + message: 警告消息 + LineNum: 行号(可选) + """ + warning = f"Warning: {message}" + if LineNum is not None: + warning += f" (line {LineNum})" + self.Warnings.append(warning) + + def LogError(self, message: str, LineNum: int = None): + """记录错误 + + Args: + message: 错误消息 + LineNum: 行号 + """ + print(f"[ERROR] {message}") + entry = {'message': message, 'line': LineNum} + self.Errors.append(entry) + + # 检查 config 中是否有 debug 文件 + DebugFile = None + if hasattr(self, 'config') and self.config: + DebugFile = getattr(self.config, 'debug', None) + + if DebugFile: + with open(DebugFile, 'a', encoding='utf-8') as f: + LineInfo = f' line {LineNum}' if LineNum else '' + f.write(f'[ERROR]{LineInfo}: {message}\n') + + def SetDebugFile(self, FilePath): + """设置调试输出文件""" + self.DebugFile = FilePath + + def DebugPrint(self, *args, **kwargs): + """输出调试信息到文件""" + if self.DebugFile: + with open(self.DebugFile, 'a', encoding='utf-8') as f: + print(*args, file=f, **kwargs) + + def HandleExpr(self, Node, UseSingleQuote=False, VarType=None): + return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType) diff --git a/lib/core/Translator/ConstEval.py b/lib/core/Translator/ConstEval.py new file mode 100644 index 0000000..780e1a2 --- /dev/null +++ b/lib/core/Translator/ConstEval.py @@ -0,0 +1,186 @@ +from __future__ import annotations + +import ast +import llvmlite.ir as ir + + +class ConstEvalMixin: + """常量表达式求值 Mixin + + 提供数组初始化常量构建与常量表达式求值能力。 + """ + + def _BuildArrayInitConstants(self, value_node, ElemType, elem_type_node, ArrayCount, Gen): + from lib.core.Handles.HandlesAssign import AssignHandle + _zv = AssignHandle._zero_value(ElemType) + _fallback = _zv if _zv is not None else ir.Constant(ElemType, ir.Undefined) + if not isinstance(value_node, (ast.List, ast.Set)): + return None + if isinstance(ElemType, ir.ArrayType): + constants = [] + for elt in value_node.elts: + if isinstance(elt, (ast.List, ast.Set)): + inner_consts = self._BuildMultiDimArrayInitConstants(elt, ElemType, Gen) + if inner_consts: + try: + constants.append(ir.Constant(ElemType, inner_consts)) + except Exception: # fallback to _fallback on constant construction failure + constants.append(_fallback) + else: + constants.append(_fallback) + else: + constants.append(_fallback) + while len(constants) < ArrayCount: + constants.append(_fallback) + return constants[:ArrayCount] + StructName = None + if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: + StructName = elem_type_node.id + constants = [] + for elt in value_node.elts: + if StructName and isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == StructName: + const = self.ClassHandler._BuildStructConstant(elt, StructName, Gen) + if const: + constants.append(const) + else: + constants.append(_fallback) + elif isinstance(elt, ast.Constant): + const = self.ClassHandler._BuildScalarConstant(elt, ElemType) + if const: + constants.append(const) + else: + constants.append(_fallback) + elif isinstance(elt, ast.UnaryOp): + const = self.ClassHandler._BuildScalarConstant(elt, ElemType) + if const: + constants.append(const) + else: + constants.append(_fallback) + elif isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == 'chr': + if elt.args and isinstance(elt.args[0], ast.Constant) and isinstance(elt.args[0].value, int): + try: + constants.append(ir.Constant(ElemType, elt.args[0].value & 0xFF)) + except Exception: # fallback to _fallback on constant construction failure + constants.append(_fallback) + else: + constants.append(_fallback) + elif isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == 'ord': + if elt.args and isinstance(elt.args[0], ast.Constant) and isinstance(elt.args[0].value, str) and len(elt.args[0].value) == 1: + try: + constants.append(ir.Constant(ElemType, ord(elt.args[0].value))) + except Exception: # fallback to _fallback on constant construction failure + constants.append(_fallback) + else: + constants.append(_fallback) + else: + const_val = self._try_eval_const_call(elt, Gen) + if const_val is not None: + try: + constants.append(ir.Constant(ElemType, const_val)) + except Exception: # fallback to _fallback on constant construction failure + constants.append(_fallback) + else: + constants.append(_fallback) + while len(constants) < ArrayCount: + constants.append(_fallback) + return constants[:ArrayCount] + + def _try_eval_const_call(self, node, Gen): + import ast + if isinstance(node, ast.Call): + func_name = None + if isinstance(node.func, ast.Name): + func_name = node.func.id + elif isinstance(node.func, ast.Attribute): + func_name = node.func.attr + if func_name: + arg_vals = [] + for arg in node.args: + v = self._try_eval_const_expr(arg, Gen) + if v is None: + return None + arg_vals.append(v) + if func_name == 'COLOR_RGB' and len(arg_vals) == 3: + r, g, b = arg_vals + return (255 << 24) | (int(b) << 16) | (int(g) << 8) | int(r) + if func_name in Gen._DefineConstants: + return Gen._DefineConstants[func_name] + for key in Gen.functions: + if key.endswith(f'__{func_name}'): + return None + return None + return self._try_eval_const_expr(node, Gen) + + def _try_eval_const_expr(self, node, Gen): + import ast + if isinstance(node, ast.Constant): + return node.value + elif isinstance(node, ast.BinOp): + left = self._try_eval_const_expr(node.left, Gen) + right = self._try_eval_const_expr(node.right, Gen) + if left is None or right is None: + return None + if isinstance(node.op, ast.Add): + return left + right + elif isinstance(node.op, ast.Sub): + return left - right + elif isinstance(node.op, ast.Mult): + return left * right + elif isinstance(node.op, ast.LShift): + return left << right + elif isinstance(node.op, ast.RShift): + return left >> right + elif isinstance(node.op, ast.BitOr): + return left | right + elif isinstance(node.op, ast.BitAnd): + return left & right + elif isinstance(node.op, ast.BitXor): + return left ^ right + elif isinstance(node, ast.UnaryOp): + operand = self._try_eval_const_expr(node.operand, Gen) + if operand is None: + return None + if isinstance(node.op, ast.USub): + return -operand + elif isinstance(node.op, ast.Invert): + return ~operand + elif isinstance(node, ast.Name): + if node.id in getattr(Gen, '_DefineConstants', {}): + return Gen._DefineConstants[node.id] + return None + + def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen): + from lib.core.Handles.HandlesAssign import AssignHandle + inner_type = ArrayType.element + count = ArrayType.count + elts = list(value_node.elts) if hasattr(value_node, 'elts') else [] + _zv = AssignHandle._zero_value(inner_type) + _fallback = _zv if _zv is not None else ir.Constant(inner_type, ir.Undefined) + constants = [] + for elt in elts: + if isinstance(inner_type, ir.ArrayType): + if isinstance(elt, (ast.List, ast.Set)): + inner_consts = self._BuildMultiDimArrayInitConstants(elt, inner_type, Gen) + if inner_consts: + constants.append(ir.Constant(inner_type, inner_consts)) + else: + constants.append(_fallback) + else: + constants.append(_fallback) + elif isinstance(elt, ast.Constant): + const = self.ClassHandler._BuildScalarConstant(elt, inner_type) + if const: + constants.append(const) + else: + constants.append(_fallback) + elif isinstance(elt, ast.UnaryOp): + const = self.ClassHandler._BuildScalarConstant(elt, inner_type) + if const: + constants.append(const) + else: + constants.append(_fallback) + else: + constants.append(_fallback) + while len(constants) < count: + constants.append(_fallback) + return constants[:count] diff --git a/lib/core/Translator/LlvmGenerator.py b/lib/core/Translator/LlvmGenerator.py new file mode 100644 index 0000000..a56d18a --- /dev/null +++ b/lib/core/Translator/LlvmGenerator.py @@ -0,0 +1,622 @@ +from __future__ import annotations + +import ast +import os +import re +import llvmlite.ir as ir + +from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +from lib.core.SymbolNode import SymbolNode +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.includes import t +from lib.constants.config import mode as _config_mode +from lib.core.Translator.BaseTranslator import _StrictLog + + +class LlvmGeneratorMixin: + """LLVM IR 生成 Mixin + + 提供 LLVM IR 直接生成、模块级 LLVM IR 处理与 C 代码生成入口能力。 + """ + + def GenerateLlvmDirect(self, Tree): + Gen = self.LlvmGen + + # 预扫描:为所有 -> str 注解的函数注册正确的返回类型 i8* + # 这样在类方法中调用这些函数时,前向声明会使用正确的类型 + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.FunctionDef): + if Node.returns and isinstance(Node.returns, ast.Name) and Node.returns.id == 'str': + Gen.known_return_types[Node.name] = ir.PointerType(ir.IntType(8)) + + # 首先收集所有 CDefine 常量,确保类定义中可以引用 + def _extract_call_const_val(node): + if isinstance(node, ast.Call): + if isinstance(node.func, ast.Attribute): + if getattr(node.func.value, 'id', None) == 't': + if node.args and isinstance(node.args[0], ast.Constant): + return node.args[0].value + elif isinstance(node.func, ast.Name): + if node.args and isinstance(node.args[0], ast.Constant): + return node.args[0].value + return None + + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value: + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) + if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': + val = None + if isinstance(Node.value, ast.Constant): + val = Node.value.value + else: + val = _extract_call_const_val(Node.value) + if val is not None: + if not hasattr(Gen, '_define_constants'): + Gen._define_constants = {} + Gen._define_constants[Node.target.id] = val + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + sym_info = _CTypeInfo() + sym_info.IsDefine = True + sym_info.DefineValue = val + self.SymbolTable[Node.target.id] = sym_info + elif isinstance(Node, ast.Assign): + for target in Node.targets: + if isinstance(target, ast.Name): + TypeInfo = None + if Node.type_comment: + try: + tc_ast = ast.parse(Node.type_comment, mode='eval') + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(tc_ast.body) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析类型注释失败: {_e}", "Exception") + if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': + val = None + if isinstance(Node.value, ast.Constant): + val = Node.value.value + else: + val = _extract_call_const_val(Node.value) + if val is not None: + if not hasattr(Gen, '_define_constants'): + Gen._define_constants = {} + Gen._define_constants[target.id] = val + from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo + sym_info = _CTypeInfo() + sym_info.IsDefine = True + sym_info.DefineValue = val + self.SymbolTable[target.id] = sym_info + + # 预扫描所有顶层函数定义,填充 FunctionDefCache(不创建 LLVM 声明) + # 这样类方法编译时遇到未声明的函数可以按需前向声明 + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.FunctionDef): + FuncName = Node.name + if FuncName not in self.FunctionDefCache: + self.FunctionDefCache[FuncName] = Node + + # 首先处理所有导入语句,确保模块在类型解析前被加载 + for Node in ast.iter_child_nodes(Tree): + Gen._set_node_info(Node) + try: + if isinstance(Node, ast.Import): + self.ImportHandler._EmitImportDeclarationsLlvm(Node, Gen) + elif isinstance(Node, ast.ImportFrom): + self.ImportHandler._EmitImportFromDeclarationsLlvm(Node, Gen) + except Exception as e: + lineno = getattr(Node, 'lineno', 0) + source_line = Gen._get_source_line(lineno) + src_file = getattr(Gen, '_current_source_file', '') + src_path = src_file if src_file else 'unknown' + line_info = "源代码 (%s, line %d)" % (src_path, lineno) + if source_line: + line_info += ":\n %d | %s" % (lineno, source_line) + self._ErrorStack.append((type(e).__name__, str(e), line_info)) + + # 预创建全局变量(带初始化器),确保类方法编译时能引用全局数组等 + Gen._current_tree = Tree + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.AnnAssign): + self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) + elif isinstance(Node, ast.Assign): + self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) + + # 前向声明所有顶层函数,确保类方法编译时能找到这些函数 + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.FunctionDef): + self.FunctionHandler._EmitFunctionForwardDeclLlvm(Node, Gen) + + # 首先处理所有类定义(包括 CUnion),确保类型定义在使用前完成 + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.ClassDef): + self.ClassHandler._EmitClassLlvm(Node, Gen) + + Gen._generate_structs() + Gen._create_Vtable_globals() + + for Node in ast.iter_child_nodes(Tree): + Gen._set_node_info(Node) + try: + if isinstance(Node, ast.Import): + continue + elif isinstance(Node, ast.ImportFrom): + continue + elif isinstance(Node, ast.ClassDef): + continue + elif isinstance(Node, ast.FunctionDef): + self.FunctionHandler._EmitFunctionLlvm(Node, Gen) + elif isinstance(Node, ast.AnnAssign): + self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) + elif isinstance(Node, ast.Assign): + self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) + elif isinstance(Node, ast.If): + pass + elif isinstance(Node, ast.Expr): + self._HandleModuleLevelExprLlvm(Node, Gen) + except Exception as e: + lineno = getattr(Node, 'lineno', 0) + source_line = Gen._get_source_line(lineno) + src_file = getattr(Gen, '_current_source_file', '') + src_path = src_file if src_file else 'unknown' + line_info = "源代码 (%s, line %d)" % (src_path, lineno) + if source_line: + line_info += ":\n %d | %s" % (lineno, source_line) + self._ErrorStack.append((type(e).__name__, str(e), line_info)) + raise + Gen._set_Vtable_initializers() + # 执行 DecoratorPass:为带自定义装饰器的函数生成 wrapper + from lib.core.DecoratorPass import run as _run_decorator_pass + _run_decorator_pass(Gen) + ir_code = Gen.finalize() + return ir_code + + def _HandleModuleLevelExprLlvm(self, Node, Gen): + if not isinstance(Node.value, ast.Call): + return + call = Node.value + if not isinstance(call.func, ast.Attribute): + return + if not isinstance(call.func.value, ast.Name) or call.func.value.id != 'c': + return + func_name = call.func.attr + if func_name == 'LLVMIR': + self._HandleModuleLevelLLVMIR(call, Gen) + + def _HandleModuleLevelLLVMIR(self, Node, Gen): + if not Node.args: + return + first_arg = Node.args[0] + if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): + ir_text = first_arg.value + elif isinstance(first_arg, ast.JoinedStr): + parts = [] + for value in first_arg.values: + if isinstance(value, ast.Constant) and isinstance(value.value, str): + parts.append(value.value) + elif isinstance(value, ast.FormattedValue): + parts.append('') + ir_text = ''.join(parts) + else: + return + self._InsertModuleLevelLLVMIR(Gen, ir_text) + + def _InsertModuleLevelLLVMIR(self, Gen, ir_text): + import re + for line in ir_text.strip().split('\n'): + line = line.strip() + if not line: + continue + module_flags_match = re.match(r'!llvm\.module\.flags\s*=\s*!\{(!\d+)\}', line) + if module_flags_match: + ref = module_flags_match.group(1) + if not hasattr(Gen, '_pending_module_flags'): + Gen._pending_module_flags = [] + Gen._pending_module_flags_refs = ref + continue + metadata_match = re.match(r'(!\d+)\s*=\s*!\{(.+)\}', line) + if metadata_match: + md_id = metadata_match.group(1) + md_body = metadata_match.group(2) + fields = [] + for field_str in re.split(r',\s*', md_body): + field_str = field_str.strip() + if not field_str: + continue + int_m = re.match(r'^i32\s+(\d+)$', field_str) + if int_m: + fields.append(ir.Constant(ir.IntType(32), int(int_m.group(1)))) + continue + str_m = re.match(r'^"([^"]*)"$', field_str) + if str_m: + fields.append(ir.MetaDataString(Gen.module, str_m.group(1))) + continue + mdstr_m = re.match(r'^!"([^"]*)"$', field_str) + if mdstr_m: + fields.append(ir.MetaDataString(Gen.module, mdstr_m.group(1))) + continue + int_m2 = re.match(r'^(\d+)$', field_str) + if int_m2: + fields.append(ir.Constant(ir.IntType(32), int(int_m2.group(1)))) + continue + ref_m = re.match(r'^(!\d+)$', field_str) + if ref_m: + fields.append(ref_m.group(1)) + continue + if fields: + if not hasattr(Gen, '_pending_metadata'): + Gen._pending_metadata = [] + Gen._pending_metadata.append((md_id, fields)) + continue + self._FlushModuleMetadata(Gen) + + def _FlushModuleMetadata(self, Gen): + if not hasattr(Gen, '_pending_metadata') or not Gen._pending_metadata: + return + md_map = {} + for md_id, fields in Gen._pending_metadata: + resolved = [] + for f in fields: + if isinstance(f, str) and f.startswith('!'): + ref = md_map.get(f) + if ref: + resolved.append(ref) + else: + resolved.append(f) + md_value = Gen.module.add_metadata(resolved) + md_map[md_id] = md_value + if hasattr(Gen, '_pending_module_flags_refs'): + ref = Gen._pending_module_flags_refs + md_node = md_map.get(ref) + if md_node: + Gen.module.add_named_metadata('llvm.module.flags', md_node) + Gen._pending_metadata = [] + Gen._pending_module_flags_refs = None + + def GenerateCCode(self, Tree, target='llvm'): + """生成代码 + + Args: + Tree: Python AST 树 + target: 目标代码类型,仅支持 'llvm' + + Returns: + 生成的代码字符串 + """ + self._generated_vars = set() + self.VarScopes = [{}] # 全局作用域 + + # 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名 + if not getattr(self, '_ImportAliases', None): + self._ImportAliases = {} + if not getattr(self, '_ImportedModules', None): + self._ImportedModules = set() + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.Import): + for alias in Node.names: + name = alias.name + if name in ('c', 't'): + continue + self._ImportedModules.add(name) + if alias.asname: + self._ImportAliases[alias.asname] = name + elif isinstance(Node, ast.ImportFrom): + module_name = Node.module + if module_name and module_name not in ('c', 't'): + self._ImportedModules.add(module_name) + for alias in Node.names: + if alias.asname: + self._ImportAliases[alias.asname] = f"{module_name}.{alias.name}" + + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.ClassDef): + ClassName = Node.name + + # 检查是否是特殊类型(枚举或联合体) + IsSpecialType = False + if Node.bases: + for base in Node.bases: + if hasattr(base, 'attr'): + if base.attr in ['CEnum', 'Enum', 'CUnion', 'REnum']: + IsSpecialType = True + break + elif hasattr(base, 'id'): + if base.id in ['CEnum', 'Enum', 'CUnion', 'REnum']: + IsSpecialType = True + break + + # 如果是特殊类型,跳过这里的处理(由 HandleClassDef 处理) + if IsSpecialType: + continue + + members = {} + IsTypedef = False + TypedefName = None + + if hasattr(Node, 'annotation') and Node.annotation: + try: + AnnotationStr = ast.dump(Node.annotation) + if 'CTypedef' in AnnotationStr: + IsTypedef = True + if isinstance(Node.annotation, ast.Call): + if Node.annotation.args: + if isinstance(Node.annotation.args[0], ast.Constant): + TypedefName = Node.annotation.args[0].value + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _config_mode + if _config_mode == "strict": + raise + _vlog().warning(f"解析 typedef 注解失败: {_e}", "Exception") + + if not IsTypedef: + for item in Node.body: + if isinstance(item, ast.Assign): + for target in item.targets: + if isinstance(target, ast.Name) and target.id == '__annotations__': + if isinstance(item.value, ast.Dict): + for key, value in zip(item.value.keys, item.value.values): + if isinstance(key, ast.Constant) and key.value == '__type__': + value_str = ast.dump(value) + if 'CTypedef' in value_str: + IsTypedef = True + if isinstance(value, ast.Call): + if value.args: + if isinstance(value.args[0], ast.Constant): + TypedefName = value.args[0].value + + if IsTypedef: + TypedefKey = TypedefName if TypedefName else ClassName + TypedefNode = SymbolNode.CreateClass( + name=TypedefKey, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', f'struct {ClassName}') + TypedefNode.set('IsComplete', True) + TypedefNode.set('file', '') + self.SymbolTable[TypedefKey] = TypedefNode.attributes + + for item in Node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + VarName = item.target.id + try: + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) + if TypeInfo is None: + TypeInfo = CTypeInfo() + TypeInfo.BaseType = t.CInt() + IsPtr = TypeInfo.IsPtr + if not IsPtr: + if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): + LeftStr = ast.dump(item.annotation.left) + RightStr = ast.dump(item.annotation.right) + if 'CPtr' in LeftStr or 'CPtr' in RightStr: + IsPtr = True + dims = [] + if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): + if isinstance(item.annotation.value, ast.Name): + if item.annotation.value.id == 't': + if hasattr(item.annotation, 'slice'): + try: + dims.append(int(item.annotation.slice.value)) + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.LogWarning(f"异常被忽略: {_e}") + MemberInfo = TypeInfo.Copy() + if dims: + MemberInfo.ArrayDims = [str(d) for d in dims] + members[VarName] = MemberInfo + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.LogWarning(f"异常被忽略: {_e}") + + if not IsTypedef: + StructNode = SymbolNode.CreateClass( + name=ClassName, + TypeKind='struct', + members=members, + lineno=0 + ) + StructNode.set('file', '') + if ClassName in self.SymbolTable: + existing = self.SymbolTable[ClassName] + if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: + StructNode.set('IsCpythonObject', True) + self.SymbolTable[ClassName] = StructNode.attributes + elif isinstance(Node, ast.FunctionDef): + FuncName = Node.name + FuncNode = SymbolNode.CreateClass( + name=FuncName, + TypeKind='function', + lineno=0 + ) + FuncNode.set('file', '') + self.SymbolTable[FuncName] = FuncNode.attributes + elif isinstance(Node, ast.AnnAssign): + if isinstance(Node.target, ast.Name): + VarName = Node.target.id + + VarType = 'unknown' + IsPtr = False + IsTypedef_assignment = False + + if Node.annotation: + try: + AnnotationStr = ast.dump(Node.annotation) + if 'CTypedef' in AnnotationStr: + IsTypedef_assignment = True + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.LogWarning(f"异常被忽略: {_e}") + + if IsTypedef_assignment and Node.value: + if isinstance(Node.value, ast.Name): + OriginalType = Node.value.id + if OriginalType in self.GeneratedTypes: + if OriginalType in self.SymbolTable: + OriginalInfo = self.SymbolTable[OriginalType] + if isinstance(OriginalInfo, dict): + actual_type = OriginalInfo.get('type', 'struct') + elif isinstance(OriginalInfo, CTypeInfo): + if OriginalInfo.IsEnum: + actual_type = 'enum' + elif OriginalInfo.IsTypedef: + actual_type = 'typedef' + elif OriginalInfo.IsStruct: + actual_type = 'struct' + else: + actual_type = 'struct' + else: + actual_type = 'struct' + if actual_type == 'enum': + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', f'enum {OriginalType}') + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + elif actual_type == 'typedef': + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + if isinstance(OriginalInfo, dict): + TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) + elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: + TypedefNode.set('OriginalType', OriginalInfo.OriginalType) + else: + TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.set('PendingTypedef', True) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + else: + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.set('PendingTypedef', True) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + self.GeneratedTypes.add(VarName) + continue + else: + if OriginalType in self.SymbolTable: + OriginalInfo = self.SymbolTable[OriginalType] + if isinstance(OriginalInfo, dict): + actual_type = OriginalInfo.get('type', 'struct') + elif isinstance(OriginalInfo, CTypeInfo): + if OriginalInfo.IsEnum: + actual_type = 'enum' + elif OriginalInfo.IsTypedef: + actual_type = 'typedef' + elif OriginalInfo.IsStruct: + actual_type = 'struct' + else: + actual_type = 'struct' + else: + actual_type = 'struct' + if actual_type == 'typedef': + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + if isinstance(OriginalInfo, dict): + TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) + elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: + TypedefNode.set('OriginalType', OriginalInfo.OriginalType) + else: + TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.set('PendingTypedef', True) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + self.GeneratedTypes.add(VarName) + if isinstance(OriginalInfo, dict): + OriginalInfo['skip_generation'] = True + continue + elif actual_type == 'struct': + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', f'struct {OriginalType}') + TypedefNode.set('PendingTypedef', True) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + self.GeneratedTypes.add(VarName) + if isinstance(OriginalInfo, dict): + OriginalInfo['skip_generation'] = True + continue + elif actual_type == 'enum': + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', f'enum {OriginalType}') + TypedefNode.set('PendingTypedef', True) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + self.GeneratedTypes.add(VarName) + if isinstance(OriginalInfo, dict): + OriginalInfo['skip_generation'] = True + continue + elif isinstance(Node.value, ast.Attribute): + from lib.core.Handles.HandlesBase import CTypeHelper + CName = CTypeHelper.GetCName(Node.value.attr) + if CName: + TypedefNode = SymbolNode.CreateClass( + name=VarName, + TypeKind='typedef', + lineno=0 + ) + TypedefNode.set('OriginalType', CName) + TypedefNode.set('file', '') + self.SymbolTable[VarName] = TypedefNode.attributes + self.GeneratedTypes.add(VarName) + continue + + if Node.annotation: + try: + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) + IsPtr = TypeInfo.IsPtr if TypeInfo else False + except Exception as _e: + if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + self.LogWarning(f"异常被忽略: {_e}") + var_node = SymbolNode.CreateClass( + name=VarName, + TypeKind='variable', + lineno=0 + ) + var_node.set('IsPtr', IsPtr) + var_node.set('file', '') + self.SymbolTable[VarName] = var_node.attributes + + self.LlvmGen = LlvmCodeGenerator( + triple=getattr(self, 'triple', None), + datalayout=getattr(self, 'datalayout', None), + ) + self.LlvmGen._Trans = self + self.LlvmGen._import_handler_ref = self.ImportHandler + if hasattr(self, '_module_sha1'): + self.LlvmGen.module_sha1 = self._module_sha1 + if hasattr(self, '_ModuleSha1Map'): + self.LlvmGen.ModuleSha1Map = self._ModuleSha1Map + if hasattr(self, '_struct_sha1_map'): + self.LlvmGen._struct_sha1_map = self._struct_sha1_map + if hasattr(self, '_temp_dir'): + self.LlvmGen._temp_dir = self._temp_dir + if hasattr(self, '_export_extern_funcs'): + self.LlvmGen._export_extern_funcs = self._export_extern_funcs + self.LlvmGen.setup_from_symbol_table(self.SymbolTable) + if hasattr(self, 'CurrentFile') and self.CurrentFile: + self.LlvmGen._set_source_info(self.CurrentFile) + + return self.GenerateLlvmDirect(Tree) diff --git a/lib/core/Translator/PythonParser.py b/lib/core/Translator/PythonParser.py new file mode 100644 index 0000000..2dcea13 --- /dev/null +++ b/lib/core/Translator/PythonParser.py @@ -0,0 +1,460 @@ +from __future__ import annotations + +import ast +import os +import sys +import json +import struct + +from lib.utils.helpers import DetectFileType +from lib.core.SymbolNode import SymbolNode +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.includes import t +from lib.constants.config import mode as _ConfigMode +from lib.core.Translator.BaseTranslator import _StrictLog + + +class PythonParserMixin: + """Python 文件解析 Mixin + + 提供辅助文件解析、symbin 文件加载与 Python 源文件解析能力。 + """ + + def ParseHelperFiles(self, HelperFiles, encoding='utf-8'): + """解析辅助文件,提取符号信息 + + 支持 .py, .c, .h 和 .symbin 文件 + """ + for FilePath in HelperFiles: + ext = DetectFileType(FilePath) + if ext == '.py': + self.ParsePythonFile(FilePath, encoding, UpdateCurrentFile=False) + elif ext == '.c': + pass # .c 文件解析已移除,不再使用旧的正则解析路径 + elif FilePath.endswith('.symbin'): + self.LoadSymbinFile(FilePath) + + def LoadSymbinFile(self, FilePath): + """从.symbin文件加载符号表 + + Args: + FilePath: .symbin文件路径 + """ + try: + with open(FilePath, 'rb') as f: + data = f.read() + + # 导入序列化函数(避免循环导入) + import sys + import os + import json + import struct + + # 解析二进制格式 + if len(data) < 4: + print(f"Warning: Invalid symbin file (too short): {FilePath}") + return + + # 解析4字节长度头(小端序) + length = struct.unpack(' 1: + # 第二个参数应该是一个列表 + dim_arg = PostdefNode.args[1] + if isinstance(dim_arg, ast.List): + for DimExpr in dim_arg.elts: + dimensions.append(DimExpr) + + # 如果没有从 Postdefinition 参数中获取维度,尝试从类型注解中的 Subscript 获取 + # 例如:memory_block_t[MAX_ORDER + 1] | t.CPtr + if not dimensions: + def extract_subscript_dims(node): + """递归提取 Subscript 节点的维度""" + dims = [] + if isinstance(node, ast.Subscript): + # 提取当前维度 + if isinstance(node.slice, ast.Constant): + dims.append(ast.Constant(value=node.slice.value)) + elif isinstance(node.slice, ast.Name): + dims.append(ast.Name(id=node.slice.id, ctx=ast.Load())) + elif isinstance(node.slice, ast.BinOp): + dims.append(node.slice) + # 递归提取更外层的维度 + dims.extend(extract_subscript_dims(node.value)) + elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + # 处理 Type | t.CPtr 的情况,检查左侧 + dims.extend(extract_subscript_dims(node.left)) + return dims + + # 从注解中提取维度 + subscript_dims = extract_subscript_dims(annotation) + if subscript_dims: + # 反转维度顺序(从内到外) + dimensions = list(reversed(subscript_dims)) + + # 获取赋值值 + value = None + if hasattr(NextNode, 'value') and NextNode.value is not None: + value = NextNode.value + + # 添加到对应的 assignments + # 对于 t.Postdefinition(...),只有包含 CTypedef 或 CPtr 时才视为 typedef 类型 + if HasCtypedef or IsPtr: + if ClassKey not in self.TypedefAssignments: + self.TypedefAssignments[ClassKey] = [] + # 如果有维度信息,使用字典存储 + if dimensions: + self.TypedefAssignments[ClassKey].append({ + 'name': TargetName, + 'IsPtr': IsPtr, + 'dimensions': dimensions, + 'value': value + }) + else: + self.TypedefAssignments[ClassKey].append((TargetName, IsPtr)) + else: + if ClassKey not in self.EmbeddedAssignments: + self.EmbeddedAssignments[ClassKey] = [] + # 如果有维度信息,使用字典存储 + if dimensions: + self.EmbeddedAssignments[ClassKey].append({ + 'name': TargetName, + 'dimensions': dimensions, + 'value': value + }) + else: + self.EmbeddedAssignments[ClassKey].append(TargetName) + + # 检查是否有 __set_default__ 初始化 + if '__set_default__' in original_AnnotationStr: + self._handle_set_default_in_parse(ClassKey, TargetName, ClassName, NextNode) + j += 1 + continue + # 再处理旧格式:xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx + # 注意:这种格式的 typedef 不应该被合并到结构体定义中, + # 而应该生成独立的 typedef 语句,所以不添加到 TypedefAssignments + elif NextNode.annotation and isinstance(NextNode.annotation, ast.Attribute): + if isinstance(NextNode.annotation.value, ast.Name): + annot_id = NextNode.annotation.value.id + annot_attr = NextNode.annotation.attr + if annot_id == 't' and NextNode.value: + if isinstance(NextNode.value, ast.Name): + ValueName = NextNode.value.id + if ValueName == ClassName: + # 检查是 CTypedef 还是 CPtr + if annot_attr == t.CPtr.__name__: + # t.CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True + if ClassKey not in self.TypedefAssignments: + self.TypedefAssignments[ClassKey] = [] + self.TypedefAssignments[ClassKey].append((TargetName, True)) + j += 1 + continue + # 注意:t.CTypedef 不在这里处理,由 HandlesAnnAssign 生成独立的 typedef 语句 + # 如果不是特殊赋值,停止收集 + break + + i = j + continue + + i += 1 + + # 提取类定义(作为结构体) + for node in ast.walk(tree): + if isinstance(node, ast.ClassDef): + ClassName = node.name + # 先把类名加入 GeneratedTypes,这样 GetTypeName 可以正确识别 + self.GeneratedTypes.add(ClassName) + + # 检测是否是 CEnum + IsCenum = False + for base in node.bases: + if isinstance(base, ast.Attribute): + BaseStr = ast.dump(base) + if 'CEnum' in BaseStr or 'REnum' in BaseStr: + IsCenum = True + break + elif isinstance(base, ast.Name): + if 'CEnum' in base.id or 'REnum' in base.id: + IsCenum = True + break + + # 检测是否有 @t.Object 装饰器或继承自 t.Object + IsCpythonObject = False + if hasattr(node, 'decorator_list') and node.decorator_list: + for decorator in node.decorator_list: + if isinstance(decorator, ast.Attribute): + if (hasattr(decorator.value, 'id') and + decorator.value.id == 't' and + decorator.attr == 'Object'): + IsCpythonObject = True + break + elif isinstance(decorator, ast.Call): + if isinstance(decorator.func, ast.Attribute): + if (hasattr(decorator.func.value, 'id') and + decorator.func.value.id == 't' and + decorator.func.attr == 'Object'): + IsCpythonObject = True + break + elif isinstance(decorator.func, ast.Name): + if decorator.func.id == 'Object': + IsCpythonObject = True + break + elif isinstance(decorator, ast.Name): + if decorator.id == 'Object': + IsCpythonObject = True + break + if not IsCpythonObject and hasattr(node, 'bases') and node.bases: + for base in node.bases: + if isinstance(base, ast.Attribute): + if (hasattr(base.value, 'id') and + base.value.id == 't' and + base.attr == 'Object'): + IsCpythonObject = True + break + elif isinstance(base, ast.Name): + if base.id == 'Object': + IsCpythonObject = True + break + + if IsCenum: + # 注册为 enum 类型 + EnumNode = SymbolNode.CreateClass( + name=ClassName, + TypeKind='enum', + lineno=0 + ) + EnumNode.set('file', '') + self.SymbolTable[ClassName] = EnumNode.attributes + + # 注册 enum 成员 + for item in node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + MemberName = item.target.id + MemberNode = CTypeInfo() + MemberNode.Name = MemberName + MemberNode.BaseType = t.CEnum(ClassName) + MemberNode.value = None + MemberNode.EnumName = ClassName + MemberNode.library_name = None + MemberNode.IsEnumMember = True + self.SymbolTable[MemberName] = MemberNode + self.SymbolTable[f"{ClassName}.{MemberName}"] = MemberNode + self.SymbolTable[f"{ClassName}_{MemberName}"] = MemberNode + + continue + + # 检测是否是 Anonymous + IsAnonymous = False + + # 提取结构体成员信息 + members = {} + for item in node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + VarName = item.target.id + try: + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) + if TypeInfo is None: + TypeInfo = CTypeInfo() + TypeInfo.BaseType = t.CInt() + IsPtr = TypeInfo.IsPtr + if not IsPtr: + if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): + LeftStr = ast.dump(item.annotation.left) + RightStr = ast.dump(item.annotation.right) + if 'CPtr' in LeftStr or 'CPtr' in RightStr: + IsPtr = True + dims = [] + if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): + if isinstance(item.annotation.value, ast.Name): + if item.annotation.value.id == 't': + if hasattr(item.annotation, 'slice'): + try: + dims.append(int(item.annotation.slice.value)) + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析数组维度失败: {_e}", "Exception") + MemberInfo = TypeInfo.Copy() + if dims: + MemberInfo.ArrayDims = [str(d) for d in dims] + members[VarName] = MemberInfo + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"解析结构体成员失败: {_e}", "Exception") + StructNode = SymbolNode.CreateClass( + name=ClassName, + TypeKind='struct', + members=members, + lineno=0, + IsCpythonObject=IsCpythonObject + ) + StructNode.set('file', '') + StructNode.set('IsAnonymous', IsAnonymous) + self.SymbolTable[ClassName] = StructNode.attributes + elif isinstance(node, ast.FunctionDef): + FuncName = node.name + FuncNode = SymbolNode.CreateClass( + name=FuncName, + TypeKind='function', + lineno=0 + ) + FuncNode.set('file', '') + self.SymbolTable[FuncName] = FuncNode.attributes + elif isinstance(node, ast.AnnAssign): + if isinstance(node.target, ast.Name): + VarName = node.target.id + # 检查是否是 t.CTypedef 格式,如果是则跳过(由 HandleClassDef 处理) + is_ctypedef = False + if node.annotation: + if isinstance(node.annotation, ast.Attribute): + if isinstance(node.annotation.value, ast.Name): + if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': + is_ctypedef = True + elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.op, ast.BitOr): + def _has_ctype(ann): + if isinstance(ann, ast.Attribute): + return hasattr(ann.value, 'id') and ann.value.id == 't' and ann.attr == 'CTypedef' + if isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): + return _has_ctype(ann.left) or _has_ctype(ann.right) + if isinstance(ann, ast.Subscript): + return _has_ctype(ann.value) + return False + if _has_ctype(node.annotation): + is_ctypedef = True + if not is_ctypedef: + IsPtr = False + if node.annotation: + try: + TypeInfo = self.TypeMergeHandler.GetCTypeInfo(node.annotation) + IsPtr = TypeInfo.IsPtr if TypeInfo else False + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"获取类型信息失败(ParsePythonFile): {_e}", "Exception") + var_node = SymbolNode.CreateClass( + name=VarName, + TypeKind='variable', + lineno=0 + ) + var_node.set('IsPtr', IsPtr) + var_node.set('file', '') + self.SymbolTable[VarName] = var_node.attributes + except Exception as e: + print(f'Warning: Failed to parse Python file {FilePath}: {e}') + + # ParseCFile 已移除 - .h/.c 文件的旧正则解析路径不再使用 + # 类型解析现在直接通过 CTypeInfo 对象进行,不经过中间字符串格式 diff --git a/lib/core/Translator/__init__.py b/lib/core/Translator/__init__.py new file mode 100644 index 0000000..84114dc --- /dev/null +++ b/lib/core/Translator/__init__.py @@ -0,0 +1,11 @@ +"""Translator 包 - 代码转换器模块""" +from lib.core.Translator.BaseTranslator import BaseTranslatorMixin, _StrictLog +from lib.core.Translator.AnnotationLoader import AnnotationLoaderMixin +from lib.core.Translator.PythonParser import PythonParserMixin +from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin +from lib.core.Translator.ConstEval import ConstEvalMixin + +__all__ = [ + 'BaseTranslatorMixin', 'AnnotationLoaderMixin', 'PythonParserMixin', + 'LlvmGeneratorMixin', 'ConstEvalMixin', '_StrictLog' +] diff --git a/lib/core/logger.py b/lib/core/VLogger.py similarity index 90% rename from lib/core/logger.py rename to lib/core/VLogger.py index 00752df..865c99a 100644 --- a/lib/core/logger.py +++ b/lib/core/VLogger.py @@ -1,297 +1,322 @@ -""" -TransPyC 彩色日志系统 -支持终端颜色输出和日志文件转储 -""" - -import sys -import os -from datetime import datetime -from typing import Optional - -# ANSI 颜色代码 -class Colors: - RESET = '\033[0m' - BOLD = '\033[1m' - DIM = '\033[2m' - UNDERLINE = '\033[4m' - - # 前景色 - BLACK = '\033[30m' - RED = '\033[31m' - GREEN = '\033[32m' - YELLOW = '\033[33m' - BLUE = '\033[34m' - MAGENTA = '\033[35m' - CYAN = '\033[36m' - WHITE = '\033[37m' - - # 高亮前景色 - BRIGHT_RED = '\033[91m' - BRIGHT_GREEN = '\033[92m' - BRIGHT_YELLOW = '\033[93m' - BRIGHT_BLUE = '\033[94m' - BRIGHT_MAGENTA = '\033[95m' - BRIGHT_CYAN = '\033[96m' - - # 背景色 - BG_RED = '\033[41m' - BG_GREEN = '\033[42m' - BG_YELLOW = '\033[43m' - BG_BLUE = '\033[44m' - BG_MAGENTA = '\033[45m' - BG_CYAN = '\033[46m' - - # 渐变颜色(用于详细日志) - GRAY = '\033[90m' - -# 检查是否支持颜色 -def supports_color(): - if not hasattr(sys.stdout, 'isatty'): - return False - if not sys.stdout.isatty(): - return False - if os.environ.get('NO_COLOR'): - return False - if os.environ.get('FORCE_COLOR'): - return True - return True - -# 全局颜色支持标志 -USE_COLORS = supports_color() - -# 日志级别 -class LogLevel: - DEBUG = 0 - INFO = 1 - WARNING = 2 - ERROR = 3 - CRITICAL = 4 - -class Logger: - def __init__(self, name: str = "TransPyC", log_file: Optional[str] = None, - level: int = LogLevel.INFO, use_colors: bool = True): - self.name = name - self.level = level - self.use_colors = use_colors and USE_COLORS - self.log_file = log_file - self.file_handler = None - - if log_file: - os.makedirs(os.path.dirname(os.path.abspath(log_file)), exist_ok=True) - self.file_handler = open(log_file, 'w', encoding='utf-8') - - # 进度跟踪 - self.current_phase = "" - self.total_items = 0 - self.current_item = 0 - - def _colorize(self, text: str, color: str) -> str: - if self.use_colors: - return f"{color}{text}{Colors.RESET}" - return text - - def _format_time(self) -> str: - return datetime.now().strftime("%H:%M:%S") - - def _write(self, message: str, level: str = ""): - # 输出到控制台 - print(message, file=sys.stdout) - sys.stdout.flush() - - # 输出到文件 - if self.file_handler: - # 文件输出不带颜色 - clean_msg = message - for color in vars(Colors).values(): - if isinstance(color, str) and color.startswith('\033'): - clean_msg = clean_msg.replace(color, '') - timestamp = self._format_time() - self.file_handler.write(f"[{timestamp}] {level} {clean_msg}\n") - self.file_handler.flush() - - def set_phase(self, phase: str, total: int = 0): - self.current_phase = phase - self.total_items = total - self.current_item = 0 - self.progress(phase, 0, total) - - def progress(self, message: str = "", current: int = 0, total: int = 0): - if total > 0: - self.total_items = total - if current > 0: - self.current_item = current - - if self.total_items > 0: - percent = (self.current_item / self.total_items) * 100 - bar_length = 30 - filled = int(bar_length * self.current_item / self.total_items) - bar = '█' * filled + '░' * (bar_length - filled) - status = f"[{self._colorize(bar, Colors.BLUE)}] {self.current_item}/{self.total_items} ({percent:.1f}%)" - else: - status = "" - - msg = f"{self._colorize('▶', Colors.BRIGHT_CYAN)} {self.current_phase}" - if status: - msg += f" {status}" - if message: - msg += f" - {message}" - - # 使用 \r 实现进度更新 - sys.stdout.write('\r' + msg) - sys.stdout.flush() - - def debug(self, message: str, category: str = ""): - if self.level > LogLevel.DEBUG: - return - - prefix = self._colorize("DEBUG", Colors.GRAY) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.GRAY)} {prefix}: {message}" - self._write(msg, "DEBUG") - - def info(self, message: str, category: str = ""): - prefix = self._colorize("INFO", Colors.GREEN) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" - self._write(msg, "INFO") - - def warning(self, message: str, category: str = ""): - prefix = self._colorize("WARN", Colors.BRIGHT_YELLOW) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.YELLOW)} {prefix}: {message}" - self._write(msg, "WARNING") - - def error(self, message: str, category: str = "", exception: Optional[Exception] = None): - prefix = self._colorize("ERROR", Colors.BRIGHT_RED) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.RED)} {prefix}: {message}" - if exception: - msg += f"\n{self._colorize('│', Colors.RED)} Exception: {type(exception).__name__}: {exception}" - self._write(msg, "ERROR") - - def critical(self, message: str, category: str = ""): - prefix = self._colorize("CRITICAL", Colors.BG_RED + Colors.WHITE + Colors.BOLD) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('╠', Colors.RED)} {prefix}: {message}" - self._write(msg, "CRITICAL") - - def success(self, message: str, category: str = ""): - prefix = self._colorize("SUCCESS", Colors.BRIGHT_GREEN) - if category: - prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" - self._write(msg, "SUCCESS") - - def compile_error(self, message: str, file: str = "", line: int = 0, code: str = ""): - """编译错误格式化输出""" - header = self._colorize("编译错误", Colors.BG_RED + Colors.WHITE + Colors.BOLD) - - msg = f"\n{self._colorize('╔', Colors.RED)}{header}{self._colorize('╗', Colors.RED)}\n" - - if file and line > 0: - location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" - msg += f"{self._colorize('║', Colors.RED)} 位置:{location}\n" - - if code: - msg += f"{self._colorize('║', Colors.RED)} 代码:{self._colorize(code, Colors.WHITE)}\n" - - msg += f"{self._colorize('║', Colors.RED)} 错误:{self._colorize(message, Colors.BRIGHT_RED)}\n" - msg += f"{self._colorize('╚', Colors.RED)}{self._colorize('═' * 50, Colors.RED)}{self._colorize('╝', Colors.RED)}" - - self._write(msg, "ERROR") - - def compile_warning(self, message: str, file: str = "", line: int = 0, code: str = ""): - """编译警告格式化输出""" - header = self._colorize("警告", Colors.BG_YELLOW + Colors.BLACK) - - msg = f"\n{self._colorize('╔', Colors.YELLOW)}{header}{self._colorize('╗', Colors.YELLOW)}\n" - - if file and line > 0: - location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" - msg += f"{self._colorize('║', Colors.YELLOW)} 位置:{location}\n" - - if code: - msg += f"{self._colorize('║', Colors.YELLOW)} 代码:{self._colorize(code, Colors.WHITE)}\n" - - msg += f"{self._colorize('║', Colors.YELLOW)} 警告:{self._colorize(message, Colors.BRIGHT_YELLOW)}\n" - msg += f"{self._colorize('╚', Colors.YELLOW)}{self._colorize('═' * 50, Colors.YELLOW)}{self._colorize('╝', Colors.YELLOW)}" - - self._write(msg, "WARNING") - - def summary(self, stats: dict): - """输出编译摘要""" - header = self._colorize("编译摘要", Colors.BG_BLUE + Colors.WHITE + Colors.BOLD) - - msg = f"\n{self._colorize('╔', Colors.BLUE)}{header}{self._colorize('╗', Colors.BLUE)}\n" - - for key, value in stats.items(): - color = Colors.GREEN if value > 0 else Colors.WHITE - msg += f"{self._colorize('║', Colors.BLUE)} {key}: {self._colorize(str(value), color)}\n" - - msg += f"{self._colorize('╚', Colors.BLUE)}{self._colorize('═' * 50, Colors.BLUE)}{self._colorize('╝', Colors.BLUE)}" - - self._write(msg, "SUMMARY") - - def close(self): - if self.file_handler: - self.file_handler.close() - self.info(f"日志已保存到:{self.log_file}") - -# 全局日志实例 -_global_logger: Optional[Logger] = None - -def get_logger(name: str = "TransPyC", log_file: Optional[str] = None, - level: int = LogLevel.INFO, use_colors: bool = True) -> Logger: - global _global_logger - if _global_logger is None: - _global_logger = Logger(name, log_file, level, use_colors) - return _global_logger - -def set_logger(logger: Logger): - global _global_logger - _global_logger = logger - -# 便捷函数 -def debug(msg, category=""): - get_logger().debug(msg, category) - -def info(msg, category=""): - get_logger().info(msg, category) - -def warning(msg, category=""): - get_logger().warning(msg, category) - -def error(msg, category="", exception=None): - get_logger().error(msg, category, exception) - -def critical(msg, category=""): - get_logger().critical(msg, category) - -def success(msg, category=""): - get_logger().success(msg, category) - -def compile_error(msg, file="", line=0, code=""): - get_logger().compile_error(msg, file, line, code) - -def compile_warning(msg, file="", line=0, code=""): - get_logger().compile_warning(msg, file, line, code) - -def set_phase(phase, total=0): - get_logger().set_phase(phase, total) - -def progress(message="", current=0, total=0): - get_logger().progress(message, current, total) - -def summary(stats): - get_logger().summary(stats) +""" +TransPyC 彩色日志系统 +支持终端颜色输出和日志文件转储 +""" + +import sys +import os +from datetime import datetime +from typing import Optional + +# ANSI 颜色代码 +class Colors: + RESET = '\033[0m' + BOLD = '\033[1m' + DIM = '\033[2m' + UNDERLINE = '\033[4m' + + # 前景色 + BLACK = '\033[30m' + RED = '\033[31m' + GREEN = '\033[32m' + YELLOW = '\033[33m' + BLUE = '\033[34m' + MAGENTA = '\033[35m' + CYAN = '\033[36m' + WHITE = '\033[37m' + + # 高亮前景色 + BRIGHT_RED = '\033[91m' + BRIGHT_GREEN = '\033[92m' + BRIGHT_YELLOW = '\033[93m' + BRIGHT_BLUE = '\033[94m' + BRIGHT_MAGENTA = '\033[95m' + BRIGHT_CYAN = '\033[96m' + + # 背景色 + BG_RED = '\033[41m' + BG_GREEN = '\033[42m' + BG_YELLOW = '\033[43m' + BG_BLUE = '\033[44m' + BG_MAGENTA = '\033[45m' + BG_CYAN = '\033[46m' + + # 渐变颜色(用于详细日志) + GRAY = '\033[90m' + +# 检查是否支持颜色 +def supports_color(): + if not hasattr(sys.stdout, 'isatty'): + return False + if not sys.stdout.isatty(): + return False + if os.environ.get('NO_COLOR'): + return False + if os.environ.get('FORCE_COLOR'): + return True + return True + +# 全局颜色支持标志 +USE_COLORS = supports_color() + +# 日志级别 +class LogLevel: + DEBUG = 0 + INFO = 1 + WARNING = 2 + ERROR = 3 + CRITICAL = 4 + +class Logger: + def __init__(self, name: str = "TransPyC", log_file: Optional[str] = None, + level: int = LogLevel.INFO, use_colors: bool = True): + self.name = name + self.level = level + self.use_colors = use_colors and USE_COLORS + self.log_file = log_file + self.file_handler = None + + if log_file: + os.makedirs(os.path.dirname(os.path.abspath(log_file)), exist_ok=True) + self.file_handler = open(log_file, 'w', encoding='utf-8') + + # 进度跟踪 + self.current_phase = "" + self.total_items = 0 + self.current_item = 0 + + def _colorize(self, text: str, color: str) -> str: + if self.use_colors: + return f"{color}{text}{Colors.RESET}" + return text + + def _format_time(self) -> str: + return datetime.now().strftime("%H:%M:%S") + + def _write(self, message: str, level: str = ""): + # 输出到控制台 + print(message, file=sys.stdout) + sys.stdout.flush() + + # 输出到文件 + if self.file_handler: + # 文件输出不带颜色 + clean_msg = message + for color in vars(Colors).values(): + if isinstance(color, str) and color.startswith('\033'): + clean_msg = clean_msg.replace(color, '') + timestamp = self._format_time() + self.file_handler.write(f"[{timestamp}] {level} {clean_msg}\n") + self.file_handler.flush() + + def set_phase(self, phase: str, total: int = 0): + self.current_phase = phase + self.total_items = total + self.current_item = 0 + self.progress(phase, 0, total) + + def progress(self, message: str = "", current: int = 0, total: int = 0): + if total > 0: + self.total_items = total + if current > 0: + self.current_item = current + + if self.total_items > 0: + percent = (self.current_item / self.total_items) * 100 + bar_length = 30 + filled = int(bar_length * self.current_item / self.total_items) + bar = '█' * filled + '░' * (bar_length - filled) + status = f"[{self._colorize(bar, Colors.BLUE)}] {self.current_item}/{self.total_items} ({percent:.1f}%)" + else: + status = "" + + msg = f"{self._colorize('▶', Colors.BRIGHT_CYAN)} {self.current_phase}" + if status: + msg += f" {status}" + if message: + msg += f" - {message}" + + # 使用 \r 实现进度更新 + sys.stdout.write('\r' + msg) + sys.stdout.flush() + + def debug(self, message: str, category: str = ""): + if self.level > LogLevel.DEBUG: + return + + prefix = self._colorize("DEBUG", Colors.GRAY) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('├', Colors.GRAY)} {prefix}: {message}" + self._write(msg, "DEBUG") + + def info(self, message: str, category: str = ""): + prefix = self._colorize("INFO", Colors.GREEN) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" + self._write(msg, "INFO") + + def warning(self, message: str, category: str = ""): + prefix = self._colorize("WARN", Colors.BRIGHT_YELLOW) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('├', Colors.YELLOW)} {prefix}: {message}" + self._write(msg, "WARNING") + + def error(self, message: str, category: str = "", exception: Optional[Exception] = None): + prefix = self._colorize("ERROR", Colors.BRIGHT_RED) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('├', Colors.RED)} {prefix}: {message}" + if exception: + msg += f"\n{self._colorize('│', Colors.RED)} Exception: {type(exception).__name__}: {exception}" + self._write(msg, "ERROR") + + def critical(self, message: str, category: str = ""): + prefix = self._colorize("CRITICAL", Colors.BG_RED + Colors.WHITE + Colors.BOLD) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('╠', Colors.RED)} {prefix}: {message}" + self._write(msg, "CRITICAL") + + def success(self, message: str, category: str = ""): + prefix = self._colorize("SUCCESS", Colors.BRIGHT_GREEN) + if category: + prefix += f"[{self._colorize(category, Colors.CYAN)}]" + + msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" + self._write(msg, "SUCCESS") + + def compile_error(self, message: str, file: str = "", line: int = 0, code: str = ""): + """编译错误格式化输出""" + header = self._colorize("编译错误", Colors.BG_RED + Colors.WHITE + Colors.BOLD) + + msg = f"\n{self._colorize('╔', Colors.RED)}{header}{self._colorize('╗', Colors.RED)}\n" + + if file and line > 0: + location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" + msg += f"{self._colorize('║', Colors.RED)} 位置:{location}\n" + + if code: + msg += f"{self._colorize('║', Colors.RED)} 代码:{self._colorize(code, Colors.WHITE)}\n" + + msg += f"{self._colorize('║', Colors.RED)} 错误:{self._colorize(message, Colors.BRIGHT_RED)}\n" + msg += f"{self._colorize('╚', Colors.RED)}{self._colorize('═' * 50, Colors.RED)}{self._colorize('╝', Colors.RED)}" + + self._write(msg, "ERROR") + + def compile_warning(self, message: str, file: str = "", line: int = 0, code: str = ""): + """编译警告格式化输出""" + header = self._colorize("警告", Colors.BG_YELLOW + Colors.BLACK) + + msg = f"\n{self._colorize('╔', Colors.YELLOW)}{header}{self._colorize('╗', Colors.YELLOW)}\n" + + if file and line > 0: + location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" + msg += f"{self._colorize('║', Colors.YELLOW)} 位置:{location}\n" + + if code: + msg += f"{self._colorize('║', Colors.YELLOW)} 代码:{self._colorize(code, Colors.WHITE)}\n" + + msg += f"{self._colorize('║', Colors.YELLOW)} 警告:{self._colorize(message, Colors.BRIGHT_YELLOW)}\n" + msg += f"{self._colorize('╚', Colors.YELLOW)}{self._colorize('═' * 50, Colors.YELLOW)}{self._colorize('╝', Colors.YELLOW)}" + + self._write(msg, "WARNING") + + def summary(self, stats: dict): + """输出编译摘要""" + header = self._colorize("编译摘要", Colors.BG_BLUE + Colors.WHITE + Colors.BOLD) + + msg = f"\n{self._colorize('╔', Colors.BLUE)}{header}{self._colorize('╗', Colors.BLUE)}\n" + + for key, value in stats.items(): + color = Colors.GREEN if value > 0 else Colors.WHITE + msg += f"{self._colorize('║', Colors.BLUE)} {key}: {self._colorize(str(value), color)}\n" + + msg += f"{self._colorize('╚', Colors.BLUE)}{self._colorize('═' * 50, Colors.BLUE)}{self._colorize('╝', Colors.BLUE)}" + + self._write(msg, "SUMMARY") + + def close(self): + if self.file_handler: + self.file_handler.close() + self.info(f"日志已保存到:{self.log_file}") + +# 全局日志实例 +_global_logger: Optional[Logger] = None + +def get_logger(name: str = "TransPyC", log_file: Optional[str] = None, + level: int = LogLevel.INFO, use_colors: bool = True) -> Logger: + global _global_logger + if _global_logger is None: + _global_logger = Logger(name, log_file, level, use_colors) + return _global_logger + +def set_logger(logger: Logger): + global _global_logger + _global_logger = logger + +# 便捷函数 +def debug(msg, category=""): + get_logger().debug(msg, category) + +def info(msg, category=""): + get_logger().info(msg, category) + +def warning(msg, category=""): + get_logger().warning(msg, category) + +def error(msg, category="", exception=None): + get_logger().error(msg, category, exception) + +def critical(msg, category=""): + get_logger().critical(msg, category) + +def success(msg, category=""): + get_logger().success(msg, category) + +def compile_error(msg, file="", line=0, code=""): + get_logger().compile_error(msg, file, line, code) + +def compile_warning(msg, file="", line=0, code=""): + get_logger().compile_warning(msg, file, line, code) + +def set_phase(phase, total=0): + get_logger().set_phase(phase, total) + +def progress(message="", current=0, total=0): + get_logger().progress(message, current, total) + +def summary(stats): + get_logger().summary(stats) + + +def safe_call(func, *args, context: str = "", **kwargs): + """安全调用函数,在异常时根据模式处理。 + + - strict 模式:重新抛出异常 + - relaxed 模式:打印彩色警告日志并返回 None + + Args: + func: 要调用的可调用对象 + *args, **kwargs: 传给 func 的参数 + context: 描述性上下文(用于日志消息) + + Returns: + func 的返回值,或 None(异常时) + """ + try: + return func(*args, **kwargs) + except Exception as e: + from lib.constants.config import mode as _ConfigMode + msg = f"{context}: {type(e).__name__}: {e}" if context else f"{type(e).__name__}: {e}" + if _ConfigMode == "strict": + raise + get_logger().warning(msg, "Exception") + return None diff --git a/lib/core/stub_generator.py b/lib/core/stub_generator.py index 76bd2e2..20d92fa 100644 --- a/lib/core/stub_generator.py +++ b/lib/core/stub_generator.py @@ -422,7 +422,7 @@ class CHeaderParser: self.variables[VarName] = { 'name': VarName, 'type': TypeStr, - 'is_ptr': IsPtr, + 'IsPtr': IsPtr, 'is_array': IsArray, 'array_size': int(ArraySize) if ArraySize and ArraySize.isdigit() else None, } @@ -452,7 +452,7 @@ class CHeaderParser: members.append({ 'name': MemberName, 'type': MemberType, - 'is_ptr': True, + 'IsPtr': True, }) continue simple_match = re.match(r'([\w\s]+?)\s+(\w+)', line) @@ -614,7 +614,7 @@ class PythonStubGenerator: if StructInfo['members']: for member in StructInfo['members']: MemberName = member['name'] - IsPtr = member.get('is_ptr', False) + IsPtr = member.get('IsPtr', False) IsArray = member.get('is_array', False) ArraySize = member.get('array_size') PyType = CTypeMapper.MapType(member['type'], IsPtr=IsPtr) @@ -636,7 +636,7 @@ class PythonStubGenerator: self.OutputLines.append(f'class {UnionName}(t.CUnion):') if UnionInfo['members']: for member in UnionInfo['members']: - PyType = CTypeMapper.MapType(member['type'], IsPtr=member.get('is_ptr', False)) + PyType = CTypeMapper.MapType(member['type'], IsPtr=member.get('IsPtr', False)) self.OutputLines.append(f' {member["name"]}: {PyType}') else: self.OutputLines.append(' pass') @@ -662,7 +662,7 @@ class PythonStubGenerator: if not self.parser.variables: return for VarName, VarInfo in self.parser.variables.items(): - PyType = CTypeMapper.MapType(VarInfo['type'], IsPtr=VarInfo['is_ptr'], IsArray=VarInfo['is_array']) + PyType = CTypeMapper.MapType(VarInfo['type'], IsPtr=VarInfo['IsPtr'], IsArray=VarInfo['is_array']) self.OutputLines.append(f'{VarName}: {PyType}') self.OutputLines.append('') diff --git a/lib/core/translator.py b/lib/core/translator.py index 55b2455..65dda2b 100644 --- a/lib/core/translator.py +++ b/lib/core/translator.py @@ -1,1726 +1,33 @@ # 核心转换逻辑 -import ast -import sys -import os -import llvmlite.ir as ir -sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'lib', 'includes')) -from ..includes import c -from ..includes import t -from typing import Dict -from lib.utils.helpers import ( - DetectFileType -) -from lib.core.Handles import ( - IfHandle, ForHandle, WhileHandle, - AnnAssignHandle, - HandlesTypeMerge, ExprHandle, BodyHandle, - ReturnHandle, AssignHandle, AugAssignHandle, DeleteHandle, - WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle, - ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle, - ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle, - CSpecialCallHandle, TSpecialCallHandle, - ClassHandle, - FunctionHandle, - ImportHandle -) -from lib.core.Handles.HandlesBase import CTypeInfo -from lib.core.SymbolTable import SymbolTable -from lib.core.SymbolNode import SymbolNode -from lib.constants.config import mode as _config_mode -from lib.core.LlvmCodeGenerator import LlvmCodeGenerator - - -def _strict_log(logger, msg): - """在 strict 模式下记录异常日志""" - if _config_mode == "strict": - logger(msg) - - -class Translator: - """代码转换器""" - - def __init__(self): - self.VarScopes = [{}] # 跟踪变量作用域,第一个是全局作用域 - self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型 - self.CurrentCReturnTypes: list = None # 当前函数的 CReturn 类型列表 - self._CurrentCpythonObjectClass: str = None # 当前正在处理的 CPython 对象类名 - self.FunctionDefCache: dict = {} # 函数定义缓存 - self.OriginalLines = [] # 原始代码行 - self.Content = '' - self.DebugFile = None # 调试输出文件路径 - self.IsHeader = False # 是否生成头文件(仅处理定义、宏、导入等,忽略函数体) - self.AnnotationModules = set() # 注解模块集合,用于识别类型定义模块 - self.Warnings = [] # 警告日志 - self._error_stack = [] # 错误栈,按顺序收集错误位置 - self.Errors = [] # 错误日志 - self.SliceCount = 0 # 切片计数 - self.SliceInfos = [] # 切片信息列表 - self.SliceLevel = 3 # 切片优化级别 - self.GeneratedTypes = set() # 在当前代码中生成的类型(struct/typedef) - self.EmbeddedAssignments = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量 - self.TypedefAssignments = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量 - self.ChainAssignmentArrays = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...] - self.tree = None # 保存解析后的 AST 树 - self.LibraryPaths = ['.'] # 库搜索路径列表,默认包含当前目录 - self.InClass = False # 是否正在处理 class 定义 - self._UserTypeModules = {} - self._source_module_sig_files = {} - self._global_function_default_args: dict = {} - self.exception_registry: dict = {} - self.exception_parents: dict = {} - self._next_exception_code: int = 100 - - # 导出表 - from lib.core.export_table import ExportTable - self.ExportTable = ExportTable(filename='') - - self.SymbolTable = SymbolTable(self) - self.IfHandler = IfHandle(self) - self.ForHandler = ForHandle(self) - self.WhileHandler = WhileHandle(self) - self.AnnAssignHandler = AnnAssignHandle(self) - self.TypeMergeHandler = HandlesTypeMerge(self) - self.ExprHandler = ExprHandle(self) - self.ExprUtils = ExprUtils(self) - self.ExprOpsHandle = ExprOpsHandle(self) - self.ExprAttrHandle = ExprAttrHandle(self) - self.ExprBuiltinHandle = ExprBuiltinHandle(self) - self.ExprAsmHandle = ExprAsmHandle(self) - self.ExprFormatHandle = ExprFormatHandle(self) - self.ExprLambdaHandle = ExprLambdaHandle(self) - self.ExprCallHandle = ExprCallHandle(self) - self.CSpecialCallHandle = CSpecialCallHandle(self) - self.TSpecialCallHandle = TSpecialCallHandle(self) - self.ClassHandler = ClassHandle(self) - self.FunctionHandler = FunctionHandle(self) - self.ImportHandler = ImportHandle(self) - self.BodyHandler = BodyHandle(self) - self.ReturnHandler = ReturnHandle(self) - self.AssignHandler = AssignHandle(self) - self.AugAssignHandler = AugAssignHandle(self) - self.DeleteHandler = DeleteHandle(self) - self.WithHandler = WithHandle(self) - self.TryHandler = TryHandle(self) - self.AssertHandler = AssertHandle(self) - self.RaiseHandler = RaiseHandle(self) - self.MatchHandler = MatchHandle(self) - - def LogWarning(self, message: str, LineNum: int = None): - """记录警告 - - Args: - message: 警告消息 - LineNum: 行号(可选) - """ - warning = f"Warning: {message}" - if LineNum is not None: - warning += f" (line {LineNum})" - self.Warnings.append(warning) - - def LogError(self, message: str, LineNum: int = None): - """记录错误 - - Args: - message: 错误消息 - LineNum: 行号 - """ - print(f"[ERROR] {message}") - entry = {'message': message, 'line': LineNum} - self.Errors.append(entry) - - # 检查 config 中是否有 debug 文件 - DebugFile = None - if hasattr(self, 'config') and self.config: - DebugFile = getattr(self.config, 'debug', None) - - if DebugFile: - with open(DebugFile, 'a', encoding='utf-8') as f: - line_info = f' line {LineNum}' if LineNum else '' - f.write(f'[ERROR]{line_info}: {message}\n') - - def _LoadAnnotationModule(self, ModuleName: str, library_name: str = None, parse_method: str = 'auto'): - """加载注解模块并将 CType 子类注册为 typedef - - 支持两种模式: - 1. AST 模式:如果 ModuleName 是文件路径,解析文件提取 CType - 2. importlib 模式:如果 ModuleName 是模块名,导入模块提取 CType - - Args: - ModuleName: 模块名或文件路径 - library_name: 手动指定的库名称,用于注册到符号表。如果为 None,则从 ModuleName 推断 - parse_method: 解析方法,可选值: - - 'auto': 自动检测(默认) - - 'file': 强制使用 AST 模式(文件路径) - - 'module': 强制使用 importlib 模式(模块名) - """ - import importlib - import importlib.util - import sys - import os - - CurrentDir = os.path.dirname(os.path.abspath(__file__)) - ProjectRoot = os.path.dirname(os.path.dirname(os.path.dirname(CurrentDir))) - if ProjectRoot not in sys.path: - sys.path.insert(0, ProjectRoot) - - def register_to_symboltable(module, lib_name: str = None, source_file: str = None): - """将模块中的 CType 子类和 CEnum 类注册到符号表""" - from lib.includes.t import CType, CEnum - count = 0 - for AttrName in dir(module): - attr = getattr(module, AttrName) - # 优先检查是否是 CEnum 子类(枚举) - if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum: - # 注册枚举类型 - EnumNode = SymbolNode.CreateClass( - name=AttrName, - TypeKind='enum', - lineno=0 - ) - EnumNode.set('enum_class', attr) - EnumNode.set('source', 'annotation_module') - EnumNode.set('library_name', lib_name) - EnumNode.set('file', source_file) - self.SymbolTable[AttrName] = EnumNode.attributes - if lib_name: - FullName = f'{lib_name}.{AttrName}' - full_EnumNode = SymbolNode.CreateClass( - name=FullName, - TypeKind='enum', - lineno=0 - ) - full_EnumNode.set('enum_class', attr) - full_EnumNode.set('source', 'annotation_module') - full_EnumNode.set('library_name', lib_name) - full_EnumNode.set('file', source_file) - self.SymbolTable[FullName] = full_EnumNode.attributes - # 枚举成员也需要注册 - for MemberName in dir(attr): - if not MemberName.startswith('_'): - member = getattr(attr, MemberName, None) - if isinstance(member, int): - MemberNode = CTypeInfo() - MemberNode.Name = MemberName - MemberNode.BaseType = t.CEnum(AttrName) - MemberNode.value = member - MemberNode.EnumName = AttrName - MemberNode.library_name = lib_name - MemberNode.IsEnumMember = True - self.SymbolTable[MemberName] = MemberNode - self.SymbolTable[f"{AttrName}.{MemberName}"] = MemberNode - self.SymbolTable[f"{AttrName}_{MemberName}"] = MemberNode - if lib_name: - self.SymbolTable[f"{lib_name}.{AttrName}.{MemberName}"] = MemberNode - self.SymbolTable[f"{lib_name}_{AttrName}_{MemberName}"] = MemberNode - count += 1 - # 检查是否是 CType 子类(typedef 别名) - elif isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: - # 继承 CType 的类是类型别名(typedef),不是结构体 - # 使用手动指定的库名称作为前缀 - if lib_name: - FullName = f'{lib_name}.{AttrName}' - else: - FullName = AttrName - # 同时注册带前缀和不带前缀的名称(都是 typedef 别名) - TypedefNode = SymbolNode.CreateClass( - name=AttrName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', attr().CName) - TypedefNode.set('source', 'annotation_module') - TypedefNode.set('library_name', lib_name) - TypedefNode.set('file', source_file) - self.SymbolTable[AttrName] = TypedefNode.attributes - if lib_name and FullName != AttrName: - FullTypedef_node = SymbolNode.CreateClass( - name=FullName, - TypeKind='typedef', - lineno=0 - ) - FullTypedef_node.set('OriginalType', attr().CName) - FullTypedef_node.set('source', 'annotation_module') - FullTypedef_node.set('library_name', lib_name) - FullTypedef_node.set('file', source_file) - self.SymbolTable[FullName] = FullTypedef_node.attributes - count += 1 - # 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef) - elif AttrName.startswith('_') and len(AttrName) > 1: - PublicName = AttrName[1:] - PublicAttr = getattr(module, PublicName, None) - if PublicAttr is not None and not isinstance(attr, type): - continue - if isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: - if PublicName not in self.SymbolTable: - if lib_name: - FullName = f'{lib_name}.{PublicName}' - else: - FullName = PublicName - TypedefNode = SymbolNode.CreateClass( - name=PublicName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', attr().CName) - TypedefNode.set('source', 'annotation_module') - TypedefNode.set('library_name', lib_name) - TypedefNode.set('file', source_file) - self.SymbolTable[PublicName] = TypedefNode.attributes - if lib_name and FullName != PublicName: - FullTypedef_node = SymbolNode.CreateClass( - name=FullName, - TypeKind='typedef', - lineno=0 - ) - FullTypedef_node.set('OriginalType', attr().CName) - FullTypedef_node.set('source', 'annotation_module') - FullTypedef_node.set('library_name', lib_name) - FullTypedef_node.set('file', source_file) - self.SymbolTable[FullName] = FullTypedef_node.attributes - count += 1 - return count - - # 确定解析方法 - use_file_mode = False - if parse_method == 'file': - use_file_mode = True - elif parse_method == 'module': - use_file_mode = False - else: # auto - use_file_mode = os.path.isfile(ModuleName) - - # 确定库名称 - lib_name = library_name - if lib_name is None: - if use_file_mode: - # 从文件路径推断库名称 - lib_name = os.path.splitext(os.path.basename(ModuleName))[0] - else: - # 模块名就是库名称 - lib_name = ModuleName - - # 根据解析方法加载模块 - if use_file_mode: - # AST 模式:使用 AST 解析文件,不执行代码 - try: - # 临时保存当前的 EmbeddedAssignments 和 TypedefAssignments - saved_embedded = self.EmbeddedAssignments.copy() - saved_typedef = self.TypedefAssignments.copy() - - # 清空 PD 收集(注解文件不应该收集 PD 语句) - self.EmbeddedAssignments = {} - self.TypedefAssignments = {} - - # 直接调用 ParsePythonFile 解析文件提取类型信息 - # 注意:这不会执行任何 Python 代码,只是解析 AST - # UpdateCurrentFile=False 表示不修改 CurrentFile - self.ParsePythonFile(ModuleName, UpdateCurrentFile=False) - - # 恢复主代码文件的 PD 收集 - self.EmbeddedAssignments = saved_embedded - self.TypedefAssignments = saved_typedef - - # 从文件名推断类型前缀(如 test_t -> test_t.xxx) - TypePrefix = lib_name - count = 0 - - # 检查符号表中新增的类型(注解文件解析后的所有 struct 类型) - # 需要检查这些类型是否继承自 CType,如果是则是 typedef 别名 - new_types = [] - for TypeName, TypeInfo in self.SymbolTable.items(): - if TypeInfo.IsStruct: - new_types.append(TypeName) - - # 再次遍历 AST,检测继承自 CType 的类 - try: - with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) - for node in ann_tree.body: - if isinstance(node, ast.ClassDef): - ClassName = node.name - # 检查是否有基类 - for base in node.bases: - if isinstance(base, ast.Name) and base.id == 'CType': - # 这个类继承自 CType,是 typedef 别名 - # 更新符号表中的类型为 typedef - if ClassName in self.SymbolTable: - TypedefNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}')) - TypedefNode.set('source', 'annotation_module') - TypedefNode.set('is_ctype_subclass', True) - self.SymbolTable[ClassName] = TypedefNode.attributes - except Exception as e: - pass # 忽略解析错误 - - # 为所有新增的类型添加库前缀和 source 标记 - for TypeName in new_types: - # 添加带前缀的类型名 - FullName = f'{TypePrefix}.{TypeName}' - TypeInfo = self.SymbolTable[TypeName].copy() - TypeInfo['source'] = 'annotation_module' - TypeInfo['original_name'] = TypeName - self.SymbolTable[FullName] = TypeInfo - count += 1 - - # 再次遍历 AST,查找注解文件中的 typedef 语句(AnnAssign with t.CTypedef) - # 注意:必须在类定义处理完之后再处理 typedef - typedef_annots = [] - # 查找 CEnum 成员变量(AnnAssign with t.CEnum | t.State 或 t.CEnum) - cEnumMembers = [] - try: - with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) - for node in ann_tree.body: - # 检测 xxx: t.CEnum 形式的枚举成员变量 - if isinstance(node, ast.AnnAssign): - if isinstance(node.target, ast.Name) and node.annotation: - TargetName = node.target.id - # 检查注解是否是 BinOp (Union) 或直接是 Attribute - IsCenum = False - if isinstance(node.annotation, ast.BinOp): - # 检查是否包含 CEnum - annot_str = ast.dump(node.annotation) - if 'CEnum' in annot_str: - IsCenum = True - elif isinstance(node.annotation, ast.Attribute): - # 直接是 t.CEnum - if node.annotation.attr == t.CEnum.__name__: - IsCenum = True - - if IsCenum: - # 检查值是否是 Constant (枚举成员值) - if node.value and isinstance(node.value, ast.Constant): - value = node.value.value - else: - value = None - cEnumMembers.append((TargetName, value)) - except Exception as e: - pass # 忽略解析错误 - - # 处理 CEnum 成员变量 - for TargetName, value in cEnumMembers: - # 注册枚举成员 - MemberNode = CTypeInfo() - MemberNode.Name = TargetName - MemberNode.BaseType = t.CEnum(TypePrefix) - MemberNode.value = value - MemberNode.EnumName = TypePrefix - MemberNode.library_name = TypePrefix - MemberNode.IsEnumMember = True - self.SymbolTable[TargetName] = MemberNode - self.SymbolTable[f"{TypePrefix}.{TargetName}"] = MemberNode - self.SymbolTable[f"{TypePrefix}_{TargetName}"] = MemberNode - - try: - with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) - for node in ann_tree.body: - # 检测 xxx: t.CTypedef = xxx 形式的 typedef 语句 - if isinstance(node, ast.AnnAssign): - if isinstance(node.target, ast.Name) and node.annotation and node.value: - TargetName = node.target.id - # 检查注解是否是 t.CTypedef - if isinstance(node.annotation, ast.Attribute): - if isinstance(node.annotation.value, ast.Name): - if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': - # 检查值是否是 Name - if isinstance(node.value, ast.Name): - original_name = node.value.id - typedef_annots.append((TargetName, original_name)) - except Exception as e: - pass # 忽略解析错误 - - # 处理 typedef 注解 - for TargetName, original_name in typedef_annots: - # 检查原始类型是否在符号表中(带前缀或不带前缀) - orig_with_prefix = f'{TypePrefix}.{original_name}' - if orig_with_prefix in self.SymbolTable: - # 添加带前缀的 typedef 别名 - FullTypedef_name = f'{TypePrefix}.{TargetName}' - TypedefNode = SymbolNode.CreateClass( - name=FullTypedef_name, - TypeKind='typedef', - lineno=0 - ) - orig_entry = self.SymbolTable.get(orig_with_prefix, {}) - orig_type_str = f'struct {original_name}' - if isinstance(orig_entry, dict): - if orig_entry.get('type') == 'typedef': - orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}') - elif orig_entry.get('type') == 'enum': - orig_type_str = f'enum {original_name}' - elif hasattr(orig_entry, 'IsTypedef') and orig_entry.IsTypedef: - orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}') - elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum: - orig_type_str = f'enum {original_name}' - TypedefNode.set('OriginalType', orig_type_str) - TypedefNode.set('source', 'annotation_module') - TypedefNode.set('original_name', TargetName) - self.SymbolTable[FullTypedef_name] = TypedefNode.attributes - count += 1 - - self.AnnotationModules.add(lib_name) - return count - except Exception as e: - # 恢复 PD 收集 - self.EmbeddedAssignments = saved_embedded - self.TypedefAssignments = saved_typedef - self.LogWarning(f"AST模式加载注解模块失败: {ModuleName}, 错误: {e}") - return 0 - else: - # importlib 模式:导入模块 - try: - module = importlib.import_module(ModuleName) - count = register_to_symboltable(module, lib_name, None) - self.AnnotationModules.add(lib_name) - return count - except ImportError: - self.LogWarning(f"importlib模式加载注解模块失败: {ModuleName}") - return 0 - except Exception as e: - self.LogWarning(f"加载注解模块失败: {ModuleName}, 错误: {e}") - return 0 - - def _LoadAnnotationFiles(self, FilePaths: list): - """加载多个注解文件并注册到符号表 - - Args: - FilePaths: 文件路径列表,每个元素可以是: - - str: 文件路径或模块名 - - tuple: (path, options) 或 (path, library_name, parse_method) - """ - for item in FilePaths: - if isinstance(item, tuple): - if len(item) >= 3: - path, library_name, parse_method = item[:3] - count = self._LoadAnnotationModule(path, library_name, parse_method) - elif len(item) == 2: - path, library_name = item - count = self._LoadAnnotationModule(path, library_name, 'auto') - else: - count = self._LoadAnnotationModule(item) - else: - count = self._LoadAnnotationModule(item) - - # 别名,保持向后兼容 - LoadAnnotationFiles = _LoadAnnotationFiles - - def SetDebugFile(self, FilePath): - """设置调试输出文件""" - self.DebugFile = FilePath - - def DebugPrint(self, *args, **kwargs): - """输出调试信息到文件""" - if self.DebugFile: - with open(self.DebugFile, 'a', encoding='utf-8') as f: - print(*args, file=f, **kwargs) - - def ParseHelperFiles(self, HelperFiles, encoding='utf-8'): - """解析辅助文件,提取符号信息 - - 支持 .py, .c, .h 和 .symbin 文件 - """ - for FilePath in HelperFiles: - ext = DetectFileType(FilePath) - if ext == '.py': - self.ParsePythonFile(FilePath, encoding, UpdateCurrentFile=False) - elif ext == '.c': - pass # .c 文件解析已移除,不再使用旧的正则解析路径 - elif FilePath.endswith('.symbin'): - self.LoadSymbinFile(FilePath) - - def LoadSymbinFile(self, FilePath): - """从.symbin文件加载符号表 - - Args: - FilePath: .symbin文件路径 - """ - try: - with open(FilePath, 'rb') as f: - data = f.read() - - # 导入序列化函数(避免循环导入) - import sys - import os - import json - import struct - - # 解析二进制格式 - if len(data) < 4: - print(f"Warning: Invalid symbin file (too short): {FilePath}") - return - - # 解析4字节长度头(小端序) - length = struct.unpack(' 1: - # 第二个参数应该是一个列表 - dim_arg = PostdefNode.args[1] - if isinstance(dim_arg, ast.List): - for DimExpr in dim_arg.elts: - dimensions.append(DimExpr) - - # 如果没有从 Postdefinition 参数中获取维度,尝试从类型注解中的 Subscript 获取 - # 例如:memory_block_t[MAX_ORDER + 1] | t.CPtr - if not dimensions: - def extract_subscript_dims(node): - """递归提取 Subscript 节点的维度""" - dims = [] - if isinstance(node, ast.Subscript): - # 提取当前维度 - if isinstance(node.slice, ast.Constant): - dims.append(ast.Constant(value=node.slice.value)) - elif isinstance(node.slice, ast.Name): - dims.append(ast.Name(id=node.slice.id, ctx=ast.Load())) - elif isinstance(node.slice, ast.BinOp): - dims.append(node.slice) - # 递归提取更外层的维度 - dims.extend(extract_subscript_dims(node.value)) - elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - # 处理 Type | t.CPtr 的情况,检查左侧 - dims.extend(extract_subscript_dims(node.left)) - return dims - - # 从注解中提取维度 - subscript_dims = extract_subscript_dims(annotation) - if subscript_dims: - # 反转维度顺序(从内到外) - dimensions = list(reversed(subscript_dims)) - - # 获取赋值值 - value = None - if hasattr(NextNode, 'value') and NextNode.value is not None: - value = NextNode.value - - # 添加到对应的 assignments - # 对于 t.Postdefinition(...),只有包含 CTypedef 或 CPtr 时才视为 typedef 类型 - if HasCtypedef or IsPtr: - if ClassKey not in self.TypedefAssignments: - self.TypedefAssignments[ClassKey] = [] - # 如果有维度信息,使用字典存储 - if dimensions: - self.TypedefAssignments[ClassKey].append({ - 'name': TargetName, - 'IsPtr': IsPtr, - 'dimensions': dimensions, - 'value': value - }) - else: - self.TypedefAssignments[ClassKey].append((TargetName, IsPtr)) - else: - if ClassKey not in self.EmbeddedAssignments: - self.EmbeddedAssignments[ClassKey] = [] - # 如果有维度信息,使用字典存储 - if dimensions: - self.EmbeddedAssignments[ClassKey].append({ - 'name': TargetName, - 'dimensions': dimensions, - 'value': value - }) - else: - self.EmbeddedAssignments[ClassKey].append(TargetName) - - # 检查是否有 __set_default__ 初始化 - if '__set_default__' in original_AnnotationStr: - self._handle_set_default_in_parse(ClassKey, TargetName, ClassName, NextNode) - j += 1 - continue - # 再处理旧格式:xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx - # 注意:这种格式的 typedef 不应该被合并到结构体定义中, - # 而应该生成独立的 typedef 语句,所以不添加到 TypedefAssignments - elif NextNode.annotation and isinstance(NextNode.annotation, ast.Attribute): - if isinstance(NextNode.annotation.value, ast.Name): - annot_id = NextNode.annotation.value.id - annot_attr = NextNode.annotation.attr - if annot_id == 't' and NextNode.value: - if isinstance(NextNode.value, ast.Name): - ValueName = NextNode.value.id - if ValueName == ClassName: - # 检查是 CTypedef 还是 CPtr - if annot_attr == t.CPtr.__name__: - # t.CPtr 表示指针变量,加入 TypedefAssignments,设置 IsPtr=True - if ClassKey not in self.TypedefAssignments: - self.TypedefAssignments[ClassKey] = [] - self.TypedefAssignments[ClassKey].append((TargetName, True)) - j += 1 - continue - # 注意:t.CTypedef 不在这里处理,由 HandlesAnnAssign 生成独立的 typedef 语句 - # 如果不是特殊赋值,停止收集 - break - - i = j - continue - - i += 1 - - # 提取类定义(作为结构体) - for node in ast.walk(tree): - if isinstance(node, ast.ClassDef): - ClassName = node.name - # 先把类名加入 GeneratedTypes,这样 GetTypeName 可以正确识别 - self.GeneratedTypes.add(ClassName) - - # 检测是否是 CEnum - IsCenum = False - for base in node.bases: - if isinstance(base, ast.Attribute): - BaseStr = ast.dump(base) - if 'CEnum' in BaseStr or 'REnum' in BaseStr: - IsCenum = True - break - elif isinstance(base, ast.Name): - if 'CEnum' in base.id or 'REnum' in base.id: - IsCenum = True - break - - # 检测是否有 @t.Object 装饰器或继承自 t.Object - IsCpythonObject = False - if hasattr(node, 'decorator_list') and node.decorator_list: - for decorator in node.decorator_list: - if isinstance(decorator, ast.Attribute): - if (hasattr(decorator.value, 'id') and - decorator.value.id == 't' and - decorator.attr == 'Object'): - IsCpythonObject = True - break - elif isinstance(decorator, ast.Call): - if isinstance(decorator.func, ast.Attribute): - if (hasattr(decorator.func.value, 'id') and - decorator.func.value.id == 't' and - decorator.func.attr == 'Object'): - IsCpythonObject = True - break - elif isinstance(decorator.func, ast.Name): - if decorator.func.id == 'Object': - IsCpythonObject = True - break - elif isinstance(decorator, ast.Name): - if decorator.id == 'Object': - IsCpythonObject = True - break - if not IsCpythonObject and hasattr(node, 'bases') and node.bases: - for base in node.bases: - if isinstance(base, ast.Attribute): - if (hasattr(base.value, 'id') and - base.value.id == 't' and - base.attr == 'Object'): - IsCpythonObject = True - break - elif isinstance(base, ast.Name): - if base.id == 'Object': - IsCpythonObject = True - break - - if IsCenum: - # 注册为 enum 类型 - EnumNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='enum', - lineno=0 - ) - EnumNode.set('file', '') - self.SymbolTable[ClassName] = EnumNode.attributes - - # 注册 enum 成员 - for item in node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - MemberName = item.target.id - MemberNode = CTypeInfo() - MemberNode.Name = MemberName - MemberNode.BaseType = t.CEnum(ClassName) - MemberNode.value = None - MemberNode.EnumName = ClassName - MemberNode.library_name = None - MemberNode.IsEnumMember = True - self.SymbolTable[MemberName] = MemberNode - self.SymbolTable[f"{ClassName}.{MemberName}"] = MemberNode - self.SymbolTable[f"{ClassName}_{MemberName}"] = MemberNode - - continue - - # 检测是否是 Anonymous - IsAnonymous = False - - # 提取结构体成员信息 - members = {} - for item in node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id - try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr - if not IsPtr: - if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): - LeftStr = ast.dump(item.annotation.left) - RightStr = ast.dump(item.annotation.right) - if 'CPtr' in LeftStr or 'CPtr' in RightStr: - IsPtr = True - dims = [] - if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): - if isinstance(item.annotation.value, ast.Name): - if item.annotation.value.id == 't': - if hasattr(item.annotation, 'slice'): - try: - dims.append(int(item.annotation.slice.value)) - except Exception as _e: - _strict_log(self.LogError, f"解析数组维度失败: {_e}") - pass - MemberInfo = TypeInfo.Copy() - if dims: - MemberInfo.ArrayDims = [str(d) for d in dims] - members[VarName] = MemberInfo - except Exception as _e: - _strict_log(self.LogError, f"解析结构体成员失败: {_e}") - pass - StructNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='struct', - members=members, - lineno=0, - IsCpythonObject=IsCpythonObject - ) - StructNode.set('file', '') - StructNode.set('IsAnonymous', IsAnonymous) - self.SymbolTable[ClassName] = StructNode.attributes - elif isinstance(node, ast.FunctionDef): - FuncName = node.name - FuncNode = SymbolNode.CreateClass( - name=FuncName, - TypeKind='function', - lineno=0 - ) - FuncNode.set('file', '') - self.SymbolTable[FuncName] = FuncNode.attributes - elif isinstance(node, ast.AnnAssign): - if isinstance(node.target, ast.Name): - VarName = node.target.id - # 检查是否是 t.CTypedef 格式,如果是则跳过(由 HandleClassDef 处理) - is_ctypedef = False - if node.annotation: - if isinstance(node.annotation, ast.Attribute): - if isinstance(node.annotation.value, ast.Name): - if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': - is_ctypedef = True - elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.op, ast.BitOr): - def _has_ctype(ann): - if isinstance(ann, ast.Attribute): - return hasattr(ann.value, 'id') and ann.value.id == 't' and ann.attr == 'CTypedef' - if isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): - return _has_ctype(ann.left) or _has_ctype(ann.right) - if isinstance(ann, ast.Subscript): - return _has_ctype(ann.value) - return False - if _has_ctype(node.annotation): - is_ctypedef = True - if not is_ctypedef: - IsPtr = False - if node.annotation: - try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(node.annotation) - IsPtr = TypeInfo.IsPtr if TypeInfo else False - except Exception as _e: - _strict_log(self.LogError, f"获取类型信息失败(ParsePythonFile): {_e}") - pass - var_node = SymbolNode.CreateClass( - name=VarName, - TypeKind='variable', - lineno=0 - ) - var_node.set('IsPtr', IsPtr) - var_node.set('file', '') - self.SymbolTable[VarName] = var_node.attributes - except Exception as e: - print(f'Warning: Failed to parse Python file {FilePath}: {e}') - - # ParseCFile 已移除 - .h/.c 文件的旧正则解析路径不再使用 - # 类型解析现在直接通过 CTypeInfo 对象进行,不经过中间字符串格式 - - def GenerateLlvmDirect(self, Tree): - Gen = self.LlvmGen - - # 预扫描:为所有 -> str 注解的函数注册正确的返回类型 i8* - # 这样在类方法中调用这些函数时,前向声明会使用正确的类型 - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.FunctionDef): - if Node.returns and isinstance(Node.returns, ast.Name) and Node.returns.id == 'str': - Gen.known_return_types[Node.name] = ir.PointerType(ir.IntType(8)) - - # 首先收集所有 CDefine 常量,确保类定义中可以引用 - def _extract_call_const_val(node): - if isinstance(node, ast.Call): - if isinstance(node.func, ast.Attribute): - if getattr(node.func.value, 'id', None) == 't': - if node.args and isinstance(node.args[0], ast.Constant): - return node.args[0].value - elif isinstance(node.func, ast.Name): - if node.args and isinstance(node.args[0], ast.Constant): - return node.args[0].value - return None - - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) - if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': - val = None - if isinstance(Node.value, ast.Constant): - val = Node.value.value - else: - val = _extract_call_const_val(Node.value) - if val is not None: - if not hasattr(Gen, '_define_constants'): - Gen._define_constants = {} - Gen._define_constants[Node.target.id] = val - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - sym_info = _CTypeInfo() - sym_info.IsDefine = True - sym_info.DefineValue = val - self.SymbolTable[Node.target.id] = sym_info - elif isinstance(Node, ast.Assign): - for target in Node.targets: - if isinstance(target, ast.Name): - TypeInfo = None - if Node.type_comment: - try: - tc_ast = ast.parse(Node.type_comment, mode='eval') - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(tc_ast.body) - except Exception as _e: - _strict_log(self.LogError, f"解析类型注释失败: {_e}") - pass - if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': - val = None - if isinstance(Node.value, ast.Constant): - val = Node.value.value - else: - val = _extract_call_const_val(Node.value) - if val is not None: - if not hasattr(Gen, '_define_constants'): - Gen._define_constants = {} - Gen._define_constants[target.id] = val - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - sym_info = _CTypeInfo() - sym_info.IsDefine = True - sym_info.DefineValue = val - self.SymbolTable[target.id] = sym_info - - # 预扫描所有顶层函数定义,填充 FunctionDefCache(不创建 LLVM 声明) - # 这样类方法编译时遇到未声明的函数可以按需前向声明 - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.FunctionDef): - FuncName = Node.name - if FuncName not in self.FunctionDefCache: - self.FunctionDefCache[FuncName] = Node - - # 首先处理所有导入语句,确保模块在类型解析前被加载 - for Node in ast.iter_child_nodes(Tree): - Gen._set_node_info(Node) - try: - if isinstance(Node, ast.Import): - self.ImportHandler._EmitImportDeclarationsLlvm(Node, Gen) - elif isinstance(Node, ast.ImportFrom): - self.ImportHandler._EmitImportFromDeclarationsLlvm(Node, Gen) - except Exception as e: - lineno = getattr(Node, 'lineno', 0) - source_line = Gen._get_source_line(lineno) - src_file = getattr(Gen, '_current_source_file', '') - src_path = src_file if src_file else 'unknown' - line_info = "源代码 (%s, line %d)" % (src_path, lineno) - if source_line: - line_info += ":\n %d | %s" % (lineno, source_line) - self._error_stack.append((type(e).__name__, str(e), line_info)) - - # 预创建全局变量(带初始化器),确保类方法编译时能引用全局数组等 - Gen._current_tree = Tree - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.AnnAssign): - self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) - elif isinstance(Node, ast.Assign): - self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) - - # 前向声明所有顶层函数,确保类方法编译时能找到这些函数 - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.FunctionDef): - self.FunctionHandler._EmitFunctionForwardDeclLlvm(Node, Gen) - - # 首先处理所有类定义(包括 CUnion),确保类型定义在使用前完成 - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.ClassDef): - self.ClassHandler._EmitClassLlvm(Node, Gen) - - Gen._generate_structs() - Gen._create_Vtable_globals() - - for Node in ast.iter_child_nodes(Tree): - Gen._set_node_info(Node) - try: - if isinstance(Node, ast.Import): - continue - elif isinstance(Node, ast.ImportFrom): - continue - elif isinstance(Node, ast.ClassDef): - continue - elif isinstance(Node, ast.FunctionDef): - self.FunctionHandler._EmitFunctionLlvm(Node, Gen) - elif isinstance(Node, ast.AnnAssign): - self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) - elif isinstance(Node, ast.Assign): - self.AssignHandler._EmitGlobalAssignLlvm(Node, Gen) - elif isinstance(Node, ast.If): - pass - elif isinstance(Node, ast.Expr): - self._HandleModuleLevelExprLlvm(Node, Gen) - except Exception as e: - lineno = getattr(Node, 'lineno', 0) - source_line = Gen._get_source_line(lineno) - src_file = getattr(Gen, '_current_source_file', '') - src_path = src_file if src_file else 'unknown' - line_info = "源代码 (%s, line %d)" % (src_path, lineno) - if source_line: - line_info += ":\n %d | %s" % (lineno, source_line) - self._error_stack.append((type(e).__name__, str(e), line_info)) - raise - Gen._set_Vtable_initializers() - # 执行 DecoratorPass:为带自定义装饰器的函数生成 wrapper - from lib.core.DecoratorPass import run as _run_decorator_pass - _run_decorator_pass(Gen) - ir_code = Gen.finalize() - return ir_code - - def _HandleModuleLevelExprLlvm(self, Node, Gen): - if not isinstance(Node.value, ast.Call): - return - call = Node.value - if not isinstance(call.func, ast.Attribute): - return - if not isinstance(call.func.value, ast.Name) or call.func.value.id != 'c': - return - func_name = call.func.attr - if func_name == 'LLVMIR': - self._HandleModuleLevelLLVMIR(call, Gen) - - def _HandleModuleLevelLLVMIR(self, Node, Gen): - if not Node.args: - return - first_arg = Node.args[0] - if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - ir_text = first_arg.value - elif isinstance(first_arg, ast.JoinedStr): - parts = [] - for value in first_arg.values: - if isinstance(value, ast.Constant) and isinstance(value.value, str): - parts.append(value.value) - elif isinstance(value, ast.FormattedValue): - parts.append('') - ir_text = ''.join(parts) - else: - return - self._InsertModuleLevelLLVMIR(Gen, ir_text) - - def _InsertModuleLevelLLVMIR(self, Gen, ir_text): - import re - for line in ir_text.strip().split('\n'): - line = line.strip() - if not line: - continue - module_flags_match = re.match(r'!llvm\.module\.flags\s*=\s*!\{(!\d+)\}', line) - if module_flags_match: - ref = module_flags_match.group(1) - if not hasattr(Gen, '_pending_module_flags'): - Gen._pending_module_flags = [] - Gen._pending_module_flags_refs = ref - continue - metadata_match = re.match(r'(!\d+)\s*=\s*!\{(.+)\}', line) - if metadata_match: - md_id = metadata_match.group(1) - md_body = metadata_match.group(2) - fields = [] - for field_str in re.split(r',\s*', md_body): - field_str = field_str.strip() - if not field_str: - continue - int_m = re.match(r'^i32\s+(\d+)$', field_str) - if int_m: - fields.append(ir.Constant(ir.IntType(32), int(int_m.group(1)))) - continue - str_m = re.match(r'^"([^"]*)"$', field_str) - if str_m: - fields.append(ir.MetaDataString(Gen.module, str_m.group(1))) - continue - mdstr_m = re.match(r'^!"([^"]*)"$', field_str) - if mdstr_m: - fields.append(ir.MetaDataString(Gen.module, mdstr_m.group(1))) - continue - int_m2 = re.match(r'^(\d+)$', field_str) - if int_m2: - fields.append(ir.Constant(ir.IntType(32), int(int_m2.group(1)))) - continue - ref_m = re.match(r'^(!\d+)$', field_str) - if ref_m: - fields.append(ref_m.group(1)) - continue - if fields: - if not hasattr(Gen, '_pending_metadata'): - Gen._pending_metadata = [] - Gen._pending_metadata.append((md_id, fields)) - continue - self._FlushModuleMetadata(Gen) - - def _FlushModuleMetadata(self, Gen): - if not hasattr(Gen, '_pending_metadata') or not Gen._pending_metadata: - return - md_map = {} - for md_id, fields in Gen._pending_metadata: - resolved = [] - for f in fields: - if isinstance(f, str) and f.startswith('!'): - ref = md_map.get(f) - if ref: - resolved.append(ref) - else: - resolved.append(f) - md_value = Gen.module.add_metadata(resolved) - md_map[md_id] = md_value - if hasattr(Gen, '_pending_module_flags_refs'): - ref = Gen._pending_module_flags_refs - md_node = md_map.get(ref) - if md_node: - Gen.module.add_named_metadata('llvm.module.flags', md_node) - Gen._pending_metadata = [] - Gen._pending_module_flags_refs = None - - def _BuildArrayInitConstants(self, value_node, ElemType, elem_type_node, ArrayCount, Gen): - from lib.core.Handles.HandlesAssign import AssignHandle - _zv = AssignHandle._zero_value(ElemType) - _fallback = _zv if _zv is not None else ir.Constant(ElemType, ir.Undefined) - if not isinstance(value_node, (ast.List, ast.Set)): - return None - if isinstance(ElemType, ir.ArrayType): - constants = [] - for elt in value_node.elts: - if isinstance(elt, (ast.List, ast.Set)): - inner_consts = self._BuildMultiDimArrayInitConstants(elt, ElemType, Gen) - if inner_consts: - try: - constants.append(ir.Constant(ElemType, inner_consts)) - except Exception: # fallback to _fallback on constant construction failure - constants.append(_fallback) - else: - constants.append(_fallback) - else: - constants.append(_fallback) - while len(constants) < ArrayCount: - constants.append(_fallback) - return constants[:ArrayCount] - StructName = None - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - StructName = elem_type_node.id - constants = [] - for elt in value_node.elts: - if StructName and isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == StructName: - const = self.ClassHandler._BuildStructConstant(elt, StructName, Gen) - if const: - constants.append(const) - else: - constants.append(_fallback) - elif isinstance(elt, ast.Constant): - const = self.ClassHandler._BuildScalarConstant(elt, ElemType) - if const: - constants.append(const) - else: - constants.append(_fallback) - elif isinstance(elt, ast.UnaryOp): - const = self.ClassHandler._BuildScalarConstant(elt, ElemType) - if const: - constants.append(const) - else: - constants.append(_fallback) - elif isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == 'chr': - if elt.args and isinstance(elt.args[0], ast.Constant) and isinstance(elt.args[0].value, int): - try: - constants.append(ir.Constant(ElemType, elt.args[0].value & 0xFF)) - except Exception: # fallback to _fallback on constant construction failure - constants.append(_fallback) - else: - constants.append(_fallback) - elif isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == 'ord': - if elt.args and isinstance(elt.args[0], ast.Constant) and isinstance(elt.args[0].value, str) and len(elt.args[0].value) == 1: - try: - constants.append(ir.Constant(ElemType, ord(elt.args[0].value))) - except Exception: # fallback to _fallback on constant construction failure - constants.append(_fallback) - else: - constants.append(_fallback) - else: - const_val = self._try_eval_const_call(elt, Gen) - if const_val is not None: - try: - constants.append(ir.Constant(ElemType, const_val)) - except Exception: # fallback to _fallback on constant construction failure - constants.append(_fallback) - else: - constants.append(_fallback) - while len(constants) < ArrayCount: - constants.append(_fallback) - return constants[:ArrayCount] - - def _try_eval_const_call(self, node, Gen): - import ast - if isinstance(node, ast.Call): - func_name = None - if isinstance(node.func, ast.Name): - func_name = node.func.id - elif isinstance(node.func, ast.Attribute): - func_name = node.func.attr - if func_name: - arg_vals = [] - for arg in node.args: - v = self._try_eval_const_expr(arg, Gen) - if v is None: - return None - arg_vals.append(v) - if func_name == 'COLOR_RGB' and len(arg_vals) == 3: - r, g, b = arg_vals - return (255 << 24) | (int(b) << 16) | (int(g) << 8) | int(r) - if func_name in Gen._define_constants: - return Gen._define_constants[func_name] - for key in Gen.functions: - if key.endswith(f'__{func_name}'): - return None - return None - return self._try_eval_const_expr(node, Gen) - - def _try_eval_const_expr(self, node, Gen): - import ast - if isinstance(node, ast.Constant): - return node.value - elif isinstance(node, ast.BinOp): - left = self._try_eval_const_expr(node.left, Gen) - right = self._try_eval_const_expr(node.right, Gen) - if left is None or right is None: - return None - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node.op, ast.BitXor): - return left ^ right - elif isinstance(node, ast.UnaryOp): - operand = self._try_eval_const_expr(node.operand, Gen) - if operand is None: - return None - if isinstance(node.op, ast.USub): - return -operand - elif isinstance(node.op, ast.Invert): - return ~operand - elif isinstance(node, ast.Name): - if node.id in getattr(Gen, '_define_constants', {}): - return Gen._define_constants[node.id] - return None - - def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen): - from lib.core.Handles.HandlesAssign import AssignHandle - inner_type = ArrayType.element - count = ArrayType.count - elts = list(value_node.elts) if hasattr(value_node, 'elts') else [] - _zv = AssignHandle._zero_value(inner_type) - _fallback = _zv if _zv is not None else ir.Constant(inner_type, ir.Undefined) - constants = [] - for elt in elts: - if isinstance(inner_type, ir.ArrayType): - if isinstance(elt, (ast.List, ast.Set)): - inner_consts = self._BuildMultiDimArrayInitConstants(elt, inner_type, Gen) - if inner_consts: - constants.append(ir.Constant(inner_type, inner_consts)) - else: - constants.append(_fallback) - else: - constants.append(_fallback) - elif isinstance(elt, ast.Constant): - const = self.ClassHandler._BuildScalarConstant(elt, inner_type) - if const: - constants.append(const) - else: - constants.append(_fallback) - elif isinstance(elt, ast.UnaryOp): - const = self.ClassHandler._BuildScalarConstant(elt, inner_type) - if const: - constants.append(const) - else: - constants.append(_fallback) - else: - constants.append(_fallback) - while len(constants) < count: - constants.append(_fallback) - return constants[:count] - - def GenerateCCode(self, Tree, target='llvm'): - """生成代码 - - Args: - Tree: Python AST 树 - target: 目标代码类型,仅支持 'llvm' - - Returns: - 生成的代码字符串 - """ - self._generated_vars = set() - self.VarScopes = [{}] # 全局作用域 - - # 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名 - if not getattr(self, '_import_aliases', None): - self._import_aliases = {} - if not getattr(self, '_imported_modules', None): - self._imported_modules = set() - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.Import): - for alias in Node.names: - name = alias.name - if name in ('c', 't'): - continue - self._imported_modules.add(name) - if alias.asname: - self._import_aliases[alias.asname] = name - elif isinstance(Node, ast.ImportFrom): - module_name = Node.module - if module_name and module_name not in ('c', 't'): - self._imported_modules.add(module_name) - for alias in Node.names: - if alias.asname: - self._import_aliases[alias.asname] = f"{module_name}.{alias.name}" - - for Node in ast.iter_child_nodes(Tree): - if isinstance(Node, ast.ClassDef): - ClassName = Node.name - - # 检查是否是特殊类型(枚举或联合体) - IsSpecialType = False - if Node.bases: - for base in Node.bases: - if hasattr(base, 'attr'): - if base.attr in ['CEnum', 'Enum', 'CUnion', 'REnum']: - IsSpecialType = True - break - elif hasattr(base, 'id'): - if base.id in ['CEnum', 'Enum', 'CUnion', 'REnum']: - IsSpecialType = True - break - - # 如果是特殊类型,跳过这里的处理(由 HandleClassDef 处理) - if IsSpecialType: - continue - - members = {} - IsTypedef = False - TypedefName = None - - if hasattr(Node, 'annotation') and Node.annotation: - try: - AnnotationStr = ast.dump(Node.annotation) - if 'CTypedef' in AnnotationStr: - IsTypedef = True - if isinstance(Node.annotation, ast.Call): - if Node.annotation.args: - if isinstance(Node.annotation.args[0], ast.Constant): - TypedefName = Node.annotation.args[0].value - except Exception: - pass - - if not IsTypedef: - for item in Node.body: - if isinstance(item, ast.Assign): - for target in item.targets: - if isinstance(target, ast.Name) and target.id == '__annotations__': - if isinstance(item.value, ast.Dict): - for key, value in zip(item.value.keys, item.value.values): - if isinstance(key, ast.Constant) and key.value == '__type__': - value_str = ast.dump(value) - if 'CTypedef' in value_str: - IsTypedef = True - if isinstance(value, ast.Call): - if value.args: - if isinstance(value.args[0], ast.Constant): - TypedefName = value.args[0].value - - if IsTypedef: - TypedefKey = TypedefName if TypedefName else ClassName - TypedefNode = SymbolNode.CreateClass( - name=TypedefKey, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {ClassName}') - TypedefNode.set('IsComplete', True) - TypedefNode.set('file', '') - self.SymbolTable[TypedefKey] = TypedefNode.attributes - - for item in Node.body: - if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id - try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr - if not IsPtr: - if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): - LeftStr = ast.dump(item.annotation.left) - RightStr = ast.dump(item.annotation.right) - if 'CPtr' in LeftStr or 'CPtr' in RightStr: - IsPtr = True - dims = [] - if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): - if isinstance(item.annotation.value, ast.Name): - if item.annotation.value.id == 't': - if hasattr(item.annotation, 'slice'): - try: - dims.append(int(item.annotation.slice.value)) - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.LogWarning(f"异常被忽略: {_e}") - MemberInfo = TypeInfo.Copy() - if dims: - MemberInfo.ArrayDims = [str(d) for d in dims] - members[VarName] = MemberInfo - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.LogWarning(f"异常被忽略: {_e}") - - if not IsTypedef: - StructNode = SymbolNode.CreateClass( - name=ClassName, - TypeKind='struct', - members=members, - lineno=0 - ) - StructNode.set('file', '') - if ClassName in self.SymbolTable: - existing = self.SymbolTable[ClassName] - if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: - StructNode.set('IsCpythonObject', True) - self.SymbolTable[ClassName] = StructNode.attributes - elif isinstance(Node, ast.FunctionDef): - FuncName = Node.name - FuncNode = SymbolNode.CreateClass( - name=FuncName, - TypeKind='function', - lineno=0 - ) - FuncNode.set('file', '') - self.SymbolTable[FuncName] = FuncNode.attributes - elif isinstance(Node, ast.AnnAssign): - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - - VarType = 'unknown' - IsPtr = False - IsTypedef_assignment = False - - if Node.annotation: - try: - AnnotationStr = ast.dump(Node.annotation) - if 'CTypedef' in AnnotationStr: - IsTypedef_assignment = True - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.LogWarning(f"异常被忽略: {_e}") - - if IsTypedef_assignment and Node.value: - if isinstance(Node.value, ast.Name): - OriginalType = Node.value.id - if OriginalType in self.GeneratedTypes: - if OriginalType in self.SymbolTable: - OriginalInfo = self.SymbolTable[OriginalType] - if isinstance(OriginalInfo, dict): - actual_type = OriginalInfo.get('type', 'struct') - elif isinstance(OriginalInfo, CTypeInfo): - if OriginalInfo.IsEnum: - actual_type = 'enum' - elif OriginalInfo.IsTypedef: - actual_type = 'typedef' - elif OriginalInfo.IsStruct: - actual_type = 'struct' - else: - actual_type = 'struct' - else: - actual_type = 'struct' - if actual_type == 'enum': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'enum {OriginalType}') - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - elif actual_type == 'typedef': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - if isinstance(OriginalInfo, dict): - TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) - elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: - TypedefNode.set('OriginalType', OriginalInfo.OriginalType) - else: - TypedefNode.set('OriginalType', f'struct {OriginalType}') - TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - else: - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {OriginalType}') - TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - self.GeneratedTypes.add(VarName) - continue - else: - if OriginalType in self.SymbolTable: - OriginalInfo = self.SymbolTable[OriginalType] - if isinstance(OriginalInfo, dict): - actual_type = OriginalInfo.get('type', 'struct') - elif isinstance(OriginalInfo, CTypeInfo): - if OriginalInfo.IsEnum: - actual_type = 'enum' - elif OriginalInfo.IsTypedef: - actual_type = 'typedef' - elif OriginalInfo.IsStruct: - actual_type = 'struct' - else: - actual_type = 'struct' - else: - actual_type = 'struct' - if actual_type == 'typedef': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - if isinstance(OriginalInfo, dict): - TypedefNode.set('OriginalType', OriginalInfo.get('OriginalType', f'struct {OriginalType}')) - elif isinstance(OriginalInfo, CTypeInfo) and OriginalInfo.OriginalType: - TypedefNode.set('OriginalType', OriginalInfo.OriginalType) - else: - TypedefNode.set('OriginalType', f'struct {OriginalType}') - TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - self.GeneratedTypes.add(VarName) - if isinstance(OriginalInfo, dict): - OriginalInfo['skip_generation'] = True - continue - elif actual_type == 'struct': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'struct {OriginalType}') - TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - self.GeneratedTypes.add(VarName) - if isinstance(OriginalInfo, dict): - OriginalInfo['skip_generation'] = True - continue - elif actual_type == 'enum': - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', f'enum {OriginalType}') - TypedefNode.set('PendingTypedef', True) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - self.GeneratedTypes.add(VarName) - if isinstance(OriginalInfo, dict): - OriginalInfo['skip_generation'] = True - continue - elif isinstance(Node.value, ast.Attribute): - from lib.core.Handles.HandlesBase import CTypeHelper - CName = CTypeHelper.GetCName(Node.value.attr) - if CName: - TypedefNode = SymbolNode.CreateClass( - name=VarName, - TypeKind='typedef', - lineno=0 - ) - TypedefNode.set('OriginalType', CName) - TypedefNode.set('file', '') - self.SymbolTable[VarName] = TypedefNode.attributes - self.GeneratedTypes.add(VarName) - continue - - if Node.annotation: - try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) - IsPtr = TypeInfo.IsPtr if TypeInfo else False - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.LogWarning(f"异常被忽略: {_e}") - var_node = SymbolNode.CreateClass( - name=VarName, - TypeKind='variable', - lineno=0 - ) - var_node.set('IsPtr', IsPtr) - var_node.set('file', '') - self.SymbolTable[VarName] = var_node.attributes - - self.LlvmGen = LlvmCodeGenerator( - triple=getattr(self, 'triple', None), - datalayout=getattr(self, 'datalayout', None), - ) - self.LlvmGen._Trans = self - self.LlvmGen._import_handler_ref = self.ImportHandler - if hasattr(self, '_module_sha1'): - self.LlvmGen.module_sha1 = self._module_sha1 - if hasattr(self, '_module_sha1_map'): - self.LlvmGen.module_sha1_map = self._module_sha1_map - if hasattr(self, '_struct_sha1_map'): - self.LlvmGen._struct_sha1_map = self._struct_sha1_map - if hasattr(self, '_temp_dir'): - self.LlvmGen._temp_dir = self._temp_dir - if hasattr(self, '_export_extern_funcs'): - self.LlvmGen._export_extern_funcs = self._export_extern_funcs - self.LlvmGen.setup_from_symbol_table(self.SymbolTable) - if hasattr(self, 'CurrentFile') and self.CurrentFile: - self.LlvmGen._set_source_info(self.CurrentFile) - - return self.GenerateLlvmDirect(Tree) - - def HandleExpr(self, Node, UseSingleQuote=False, VarType=None): - return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType) +# 通过 Mixin 模式组合各功能模块 +# +# 拆分后的模块位于 lib/core/Translator/ 目录下: +# - BaseTranslator.py: __init__、日志、Handle 实例化 +# - AnnotationLoader.py: 注解模块加载 +# - PythonParser.py: Python 文件解析 +# - LlvmGenerator.py: LLVM IR 生成 +# - ConstEval.py: 常量表达式求值 + +from lib.core.Translator.BaseTranslator import BaseTranslatorMixin, _StrictLog +from lib.core.Translator.AnnotationLoader import AnnotationLoaderMixin +from lib.core.Translator.PythonParser import PythonParserMixin +from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin +from lib.core.Translator.ConstEval import ConstEvalMixin + + +class Translator( + BaseTranslatorMixin, + AnnotationLoaderMixin, + PythonParserMixin, + LlvmGeneratorMixin, + ConstEvalMixin, +): + """代码转换器 + + 通过 Mixin 模式组合各功能模块。 + 实际方法实现分布在 lib/core/Translator/ 下的各模块中。 + """ + pass + + +__all__ = ['Translator', '_StrictLog'] diff --git a/lib/includes/t.py b/lib/includes/t.py index 450e83a..09400d5 100644 --- a/lib/includes/t.py +++ b/lib/includes/t.py @@ -56,8 +56,12 @@ def _build_type_maps(): if _cname and _obj.IsBasicType(): _BASIC_TYPES_MAP[_cname] = _cname _T_TYPE_PATTERNS.append((_name, _cname)) - except Exception: - pass + except Exception as _e: + from lib.core.VLogger import get_logger as _vlog + from lib.constants.config import mode as _ConfigMode + if _ConfigMode == "strict": + raise + _vlog().warning(f"构建类型映射时实例化 CType 子类失败: {_e}", "Exception") # ============================================================================= diff --git a/temp_error.txt b/temp_error.txt deleted file mode 100644 index cdcc976..0000000 --- a/temp_error.txt +++ /dev/null @@ -1 +0,0 @@ -[编译终止] 1 个文件翻译失败 diff --git a/temp_error2.txt b/temp_error2.txt deleted file mode 100644 index cdcc976..0000000 --- a/temp_error2.txt +++ /dev/null @@ -1 +0,0 @@ -[编译终止] 1 个文件翻译失败 diff --git a/test_debug.py b/test_debug.py deleted file mode 100644 index 3546fbc..0000000 --- a/test_debug.py +++ /dev/null @@ -1,32 +0,0 @@ -import sys, ast -sys.path.insert(0, '.') -from lib.includes.t import CTypeRegistry -CTypeRegistry._build() - -from lib.core.Handles.HandlesBase import CTypeInfo -from lib.core.Handles.HandlesTypeMerge import TypeMergeHandler -from lib.includes import t - -class MockTrans: - SymbolTable = {} - -trans = MockTrans() -handler = TypeMergeHandler(trans) - -# Parse "t.CVoid | t.CPtr" -code = "t.CVoid | t.CPtr" -tree = ast.parse(code, mode='eval') -binop = tree.body - -result = handler.MergeTypes(binop) -if result: - print(f'MergeTypes(t.CVoid | t.CPtr):') - print(f' BaseType: {result.BaseType}') - print(f' PtrCount: {result.PtrCount}') - print(f' IsVoid: {result.IsVoid}') - print(f' IsPtr: {result.IsPtr}') - print(f' IsTypedef: {result.IsTypedef}') - print(f' Name: {result.Name}') - print(f' ToString: {result.ToString()}') -else: - print('MergeTypes returned None') diff --git a/test_regex.py b/test_regex.py deleted file mode 100644 index ac04290..0000000 --- a/test_regex.py +++ /dev/null @@ -1,24 +0,0 @@ -import re - -name = '1347c4edf991da6f.Widget' -ir_text = '%1347c4edf991da6f.Widget = type { i8*, i32, i32, i32, i32, i32, i8*, i32, i32, i32 }' -pattern = r'%' + re.escape(name) + r'(?=[^a-zA-Z0-9_$\.]|$)' -print('Pattern:', pattern) -m = re.search(pattern, ir_text) -if m: - print('Match:', m.group(0)) -else: - print('No match') - -result = re.sub(pattern, r'%"' + name + r'"', ir_text) -print('Result:', result) - -ir_text2 = '%"1347c4edf991da6f.Widget" = type { i8*, i32, i32, i32, i32, i32, i8*, i32, i32, i32 }' -m2 = re.search(pattern, ir_text2) -if m2: - print('Match2:', m2.group(0)) -else: - print('No match2') - -result2 = re.sub(pattern, r'%"' + name + r'"', ir_text2) -print('Result2:', result2) diff --git a/test_sret b/test_sret deleted file mode 100644 index 6cf51f7..0000000 --- a/test_sret +++ /dev/null @@ -1,27 +0,0 @@ -=== AST Tree (Compact) === -Module(body=[Import(names=[alias(name='t'), alias(name='c')]), FunctionDef(name='get_rect', args=arguments(posonlyargs=[], args=[arg(arg='style', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())), arg(arg='th', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())), arg(arg='wx', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())), arg(arg='wy', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())), arg(arg='ww', annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()))], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[AnnAssign(target=Name(id='btn_w', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=10), simple=1), AnnAssign(target=Name(id='btn_h', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=10), simple=1), AnnAssign(target=Name(id='btn_x', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=BinOp(left=BinOp(left=BinOp(left=Name(id='wx', ctx=Load()), op=Add(), right=Name(id='ww', ctx=Load())), op=Sub(), right=Name(id='btn_w', ctx=Load())), op=Sub(), right=Constant(value=4)), simple=1), AnnAssign(target=Name(id='btn_y', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=BinOp(left=Name(id='wy', ctx=Load()), op=Add(), right=BinOp(left=BinOp(left=Name(id='th', ctx=Load()), op=Sub(), right=Name(id='btn_h', ctx=Load())), op=FloorDiv(), right=Constant(value=2))), simple=1), AnnAssign(target=Name(id='max_bx', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=BinOp(left=Name(id='btn_x', ctx=Load()), op=Sub(), right=Constant(value=2)), simple=1), AnnAssign(target=Name(id='min_bx', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=BinOp(left=Name(id='max_bx', ctx=Load()), op=Sub(), right=Constant(value=2)), simple=1), Return(value=Tuple(elts=[Name(id='btn_w', ctx=Load()), Name(id='btn_h', ctx=Load()), Name(id='btn_x', ctx=Load()), Name(id='btn_y', ctx=Load()), Name(id='max_bx', ctx=Load()), Name(id='min_bx', ctx=Load())], ctx=Load()))], decorator_list=[Call(func=Attribute(value=Name(id='c', ctx=Load()), attr='CReturn', ctx=Load()), args=[Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())], keywords=[])], returns=Subscript(value=Name(id='tuple', ctx=Load()), slice=Tuple(elts=[Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load())], ctx=Load()), ctx=Load()), type_params=[]), FunctionDef(name='main', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[AnnAssign(target=Name(id='bw', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='bh', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='bx', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='by', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='mbx', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), AnnAssign(target=Name(id='mnbx', ctx=Store()), annotation=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), value=Constant(value=0), simple=1), Assign(targets=[Tuple(elts=[Name(id='bw', ctx=Store()), Name(id='bh', ctx=Store()), Name(id='bx', ctx=Store()), Name(id='by', ctx=Store()), Name(id='mbx', ctx=Store()), Name(id='mnbx', ctx=Store())], ctx=Store())], value=Call(func=Name(id='get_rect', ctx=Load()), args=[Constant(value=1), Constant(value=30), Constant(value=100), Constant(value=200), Constant(value=800)], keywords=[])), Expr(value=Call(func=Name(id='printf', ctx=Load()), args=[Constant(value='btn_w=%d btn_h=%d btn_x=%d btn_y=%d max_bx=%d min_bx=%d\n'), Name(id='bw', ctx=Load()), Name(id='bh', ctx=Load()), Name(id='bx', ctx=Load()), Name(id='by', ctx=Load()), Name(id='mbx', ctx=Load()), Name(id='mnbx', ctx=Load())], keywords=[])), Return(value=Constant(value=0))], decorator_list=[], returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()), type_params=[])], type_ignores=[]) - -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t -[GetCTypeInfo] Node type: Attribute, dump: Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=L... -[GetCTypeInfo-Attribute] 查询: 'CInt' ModulePath: t