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