feat(tpc): 类型解析 fail-fast 报文补充完整定位信息
报错从单行"类型注解 X 无法解析"改为分层多行: ① SymbolTable._LoadSymbolsFromFile 加 文件路径 + 模块命名空间 + 发起行; ② SymbolTypeResolver._resolve_function 加 函数名/行号/形参序号与形参名 + 注解源码原文 (新增 _AnnotationText 渲染 Name/Attribute/Subscript/BinOp/Tuple/Constant); ③ LLVMTypeMapper._resolve_name 列出全部已试来源(内置速记/BuiltinTypeMap/ builtins CTypedef/符号表 typedef/本模块类名数/枚举名数/符号表已加载条目数)与注解行列, 并给出"是否声明模块未先加载"的排查提示。 样例(VET/temp/24da8b5f154f7cc0.vpi): 函数 'open'(第 107 行)的返回类型无法解析 / 注解写法:INT | t.State / 裸名 'INT' ...
This commit is contained in:
1 parent
14af03577c
commit
8b657b9ac2
3 files changed
+54
-10
No files matched your search
@@ -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 节点"""
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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 值解析
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user