diff --git a/lib/core/LLVMTypeMapper.py b/lib/core/LLVMTypeMapper.py index d481f62..ea62f90 100644 --- a/lib/core/LLVMTypeMapper.py +++ b/lib/core/LLVMTypeMapper.py @@ -288,9 +288,22 @@ class LLVMTypeMapper: if builtin_llvm: return builtin_llvm # fail-fast:类型信息缺失不再静默退化成 i32 + _node_line: object = getattr(node, 'lineno', None) + _node_col: object = getattr(node, 'col_offset', None) + _pos: str = "" + if _node_line: + _pos = f"(注解位置 第 {_node_line} 行" + _pos += f", 列 {_node_col})" if _node_col is not None else ")" + _loaded_cnt: int = len(getattr(self._symtab, '_symbols', None) or {}) raise TypeNameUnresolvedError( - f"类型注解 '{node.id}' 无法解析:既不是内置类型 / 符号表 typedef / " - f"builtins typedef,也不是本模块或已加载模块的类/枚举") + f"裸名 '{node.id}' 无法解析为类型{_pos}\n" + f" · 已尝试的解析来源(全部 miss):内置类型速记 / BuiltinTypeMap / " + f"builtins.vp 的 CTypedef / 符号表 typedef / " + f"本模块类名({len(self._ClassNames)} 个)/ 本模块枚举名({len(self._EnumWidths)} 个)/ " + f"符号表已加载条目({_loaded_cnt} 个)中的类与枚举\n" + f" · 若该名字确实是 typedef / 类:先确认声明它的模块已在本模块之前加载" + f"(未加载 ⇒ 符号表里没有它,与注解拼写无关);否则按「注解拼写错误或" + f"该类型不存在」处理") def _resolve_attribute(self, node: ast.Attribute) -> str: """解析 ast.Attribute 节点""" diff --git a/lib/core/SymbolTable.py b/lib/core/SymbolTable.py index 98b1e36..8331db7 100644 --- a/lib/core/SymbolTable.py +++ b/lib/core/SymbolTable.py @@ -400,11 +400,15 @@ class SymbolTable: return loaded - except TypeNameUnresolvedError: + except TypeNameUnresolvedError as e: # 类型解析 fail-fast:**不再**吞成"加载模块失败"后返回空符号表 # (那会让该模块的全部符号缺失,错误在下游以"找不到类/函数"的面目炸开, - # 根因被掩盖)。直接上抛 → 上层终止编译并打印带函数名/形参名的报文。 - raise + # 根因被掩盖)。补上文件/模块定位后上抛 → 上层终止编译。 + raise TypeNameUnresolvedError( + f"[类型解析失败] 声明文件 {FilePath}\n" + f" 模块命名空间:{namespace_prefix}\n" + f" 第 {lineno} 行发起加载(lineno=0 表示解析声明文件本身)\n" + f" {e}") from None except Exception as e: _vlog().error(traceback.format_exc()) self.diagnostics.error(FilePath, lineno, f"加载模块失败: {e}") diff --git a/lib/core/SymbolTypeResolver.py b/lib/core/SymbolTypeResolver.py index fa0ed6d..58fe0c7 100644 --- a/lib/core/SymbolTypeResolver.py +++ b/lib/core/SymbolTypeResolver.py @@ -218,9 +218,11 @@ class TypeResolver: try: func.ret_type = self._type_mapper.get_func_ret_type_str(func.returns_node) except TypeNameUnresolvedError as _e: - # fail-fast:返回类型无法解析 → 终止编译(附函数名定位,不降级为 i32) + # fail-fast:返回类型无法解析 → 终止编译(附函数名/行号/注解原文定位) raise TypeNameUnresolvedError( - f"函数 '{func.name}' 的返回类型无法解析:{_e}") from None + f"函数 '{func.name}'(第 {func.lineno} 行)的返回类型无法解析\n" + f" 注解写法:{TypeResolver._AnnotationText(func.returns_node)}\n" + f" {_e}") from None # 同时解析为 CTypeInfo,保留符号性(LLVM 类型字符串 'i64' 不区分有无符号) if func.returns_node is not None: try: @@ -230,17 +232,42 @@ class TypeResolver: func.param_types = [] _arg_name: str annotation: ast.expr | None - for _arg_name, annotation in func.params: + _idx: int + for _idx, (_arg_name, annotation) in enumerate(func.params): if annotation: try: func.param_types.append(self._type_mapper.get_func_param_type_str(annotation)) except TypeNameUnresolvedError as _e: - # fail-fast:形参类型无法解析 → 终止编译(附函数名/形参名定位) + # fail-fast:形参类型无法解析 → 终止编译(附函数名/序号/形参名/注解原文) raise TypeNameUnresolvedError( - f"函数 '{func.name}' 的形参 '{_arg_name}' 类型无法解析:{_e}") from None + f"函数 '{func.name}'(第 {func.lineno} 行)的第 {_idx} 个形参 " + f"'{_arg_name}' 类型无法解析\n" + f" 注解写法:{TypeResolver._AnnotationText(annotation)}\n" + f" {_e}") from None else: func.param_types.append('i8*') + @staticmethod + def _AnnotationText(node: ast.AST | None) -> str: + """把类型注解节点渲染成源码形态(仅用于 fail-fast 报错定位,不求完备)""" + if node is None: + return '' + if isinstance(node, ast.Name): + return node.id or '?' + if isinstance(node, ast.Attribute): + return f"{TypeResolver._AnnotationText(node.value)}.{node.attr}" + if isinstance(node, ast.Subscript): + return (f"{TypeResolver._AnnotationText(node.value)}" + f"[{TypeResolver._AnnotationText(node.slice)}]") + if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + return (f"{TypeResolver._AnnotationText(node.left)} | " + f"{TypeResolver._AnnotationText(node.right)}") + if isinstance(node, (ast.Tuple, ast.List)): + return ', '.join(TypeResolver._AnnotationText(e) for e in (node.elts or [])) + if isinstance(node, ast.Constant): + return repr(node.value) + return f'<{type(node).__name__}>' + # ------------------------------------------------------------------ # Define 值解析 # ------------------------------------------------------------------