From 369afb5011d4b85e93e52000c1659900d86ee9ee Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 18 Oct 2026 19:50:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(generic):=20=E6=81=A2=E5=A4=8D=E6=B3=9B?= =?UTF-8?q?=E5=9E=8B=E7=89=B9=E5=8C=96=E5=8F=91=E5=B0=84=E4=B8=BB=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补回 _specialize_generic_class 的 deepcopy/改名/字段与方法 T 替换/_EmitClassLlvm 发射逻辑,list[...].__len__ 与 get 正常生成;源码不再支持 CPtr[...],统一写 T*;编译错误只由主进程输出一次。 --- Projectrans.py | 6 ++ lib/Projectrans/Phase2Translator.py | 140 ++++++++++++++++----------- lib/core/Handles/HandlesClassDef.py | 104 ++++++++++++++++++++ lib/core/Handles/HandlesExprCall.py | 6 +- lib/core/Handles/HandlesExprUtils.py | 8 +- lib/core/Handles/HandlesFunctions.py | 54 +++++++---- lib/core/Handles/HandlesImports.py | 5 +- lib/core/Handles/HandlesTypeMerge.py | 21 ++-- lib/core/SymbolUtils.py | 3 +- lib/core/TypeAnnotationResolver.py | 8 +- lib/vast/ExprParser.py | 48 +++++++-- lib/vast_c/_parser.pyd | Bin 235985 -> 238550 bytes lib/vast_c/vast_c.c | 105 ++++++++++++++++++++ 13 files changed, 413 insertions(+), 95 deletions(-) diff --git a/Projectrans.py b/Projectrans.py index 9b8b811..e09283e 100644 --- a/Projectrans.py +++ b/Projectrans.py @@ -32,6 +32,7 @@ if __name__ == '__main__': import sys as _sys import time as _time from lib.Projectrans.Phase2Translator import GetProfRunDir as _GetProfRunDir + from lib.Projectrans.Phase2Translator import ReportedCompileError as _ReportedCompileError _main_prof: _cProfile.Profile = _cProfile.Profile() _main_prof.enable() @@ -39,6 +40,11 @@ if __name__ == '__main__': try: main() _timing_status: str = '成功' + except _ReportedCompileError: + # 完整错误(含源码定位)已由主进程打印过一次:这里只置失败并退出, + # 不再重复输出同一错误。 + _timing_status = '失败' + raise SystemExit(1) except (TypeError, SyntaxError) as _e: _timing_status = '失败' import re as _re diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index d464d24..91b2255 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -27,6 +27,15 @@ from StubGen import PythonToStubConverter from lib.core.LLVMCG.IRMetadataFix import SanitizeIRMetadata +class ReportedCompileError(RuntimeError): + """主进程已输出完整编译错误(含源码定位)的终止信号。 + + 该异常只用于"错误已经打印过"的路径:main()/run() 抛出后, + 顶层入口(Projectrans.py)不得再次打印错误内容,直接以失败退出码结束, + 否则同一错误会在 worker/主进程/顶层各出现一遍。 + """ + + # PROF 热点:nt._path_isfile 2.6 万次 16.4s(Windows 磁盘 stat ~0.6ms/次)。 # 编译进程内文件状态稳定(obj/ll 一旦生成不删除、不被移动),用模块级缓存 # 避免重复 stat。仅用于"存在性检查"类调用(不用于内容变化的判断)。 @@ -763,11 +772,9 @@ def _parallel_translate_worker(src_path: str, out_path: str, src_root: str, temp trans._translate_file(src_path, out_path, prebuilt_ModuleSha1Map=prebuilt_ModuleSha1Map, dwarf_enabled=dwarf_enabled) return ('ok', src_path, '') except Exception as e: - # fail-fast:只输出单行错误(含源码定位),不打印 Python 内部调用栈 - sys.stderr.write( - f"[FATAL] 翻译失败: {src_path}\n{type(e).__name__}: {e}\n") - sys.stderr.flush() - os._exit(88) + # fail-fast:worker 不写 stderr,只把错误(含源码定位)返回主进程; + # 由主进程统一输出一次,避免同一错误打印两遍。 + return ('error', src_path, f'{type(e).__name__}: {e}') def _parallel_translate_batch(batch: list, src_root: str, temp_dir: str, output_dir: str, @@ -787,7 +794,10 @@ def _parallel_translate_batch(batch: list, src_root: str, temp_dir: str, output_ 批内每个文件翻译前从 symbol_table_bytes 反序列化出干净副本,前文件的 符号写入不会残留到后文件(否则跨模块 struct 类型前缀错位)。 返回 (错误列表[(src_path, err)], batch, per_file_times[(src_path, elapsed, rel)])。 + 错误只回传、不写 stderr:完整错误由主进程统一输出一次(含源码定位)。 """ + _current_src: str = batch[0][1] if batch else '' + per_file_times: list[tuple[str, float, str]] = [] try: trans = Phase2Translator(src_root, temp_dir, output_dir, compile_cmd='llc', include_dirs=include_dirs, @@ -830,28 +840,21 @@ def _parallel_translate_batch(batch: list, src_root: str, temp_dir: str, output_ trans._build_shared_symbol_data() batch_errors: list = [] - per_file_times: list[tuple[str, float, str]] = [] for _i, src_path, out_path, _sha1, msm in batch: _f0: float = time.time() - try: - # 每文件前重置 SymbolTable 为干净副本(防跨文件污染) - if symbol_table_bytes is not None: - trans._shared_symbol_table = pickle.loads(symbol_table_bytes) - trans._shared_symbol_table.translator = None - trans._translate_file(src_path, out_path, prebuilt_ModuleSha1Map=msm, dwarf_enabled=dwarf_enabled) - per_file_times.append((src_path, time.time() - _f0, os.path.relpath(src_path, src_root))) - except Exception as e: - # fail-fast(2026-08-18):任意文件编译出错立即终止整个编译进程, - # 不再收集错误继续翻译批内剩余文件(避免浪费大量时间)。主进程 - # 收到 BrokenProcessPool/future 异常后取消全部剩余批次退出。 - sys.stderr.write( - f"[FATAL] 文件翻译失败: {src_path}\n" - f"{type(e).__name__}: {e}\n") - sys.stderr.flush() - os._exit(88) + _current_src = src_path + # 每文件前重置 SymbolTable 为干净副本(防跨文件污染) + if symbol_table_bytes is not None: + trans._shared_symbol_table = pickle.loads(symbol_table_bytes) + trans._shared_symbol_table.translator = None + trans._translate_file(src_path, out_path, prebuilt_ModuleSha1Map=msm, dwarf_enabled=dwarf_enabled) + per_file_times.append((src_path, time.time() - _f0, os.path.relpath(src_path, src_root))) return (batch_errors, batch, per_file_times) except Exception as e: - return ([(item[1], f'{type(e).__name__}: {e}') for item in batch], batch, []) + # fail-fast:任意文件编译出错立即终止本批(不再翻译批内剩余文件)。 + # worker 不写 stderr —— 错误(含源码定位)随返回值交给主进程统一输出一次。 + _src: str = _current_src or (batch[0][1] if batch else '') + return ([(_src, f'{type(e).__name__}: {e}')], batch, per_file_times) # ================================================================== @@ -1709,7 +1712,6 @@ class Phase2Translator: _vlog().warning(f"符号表序列化失败({e}),worker将自行构建") shared_pickle_path = '' - errors = [] # 复用 self._executor_pool:避免局部变量 GC 时 finalizer 阻塞 ~99s # (join_executor_internals 在 GC 时同步等待 worker 退出队列) if self._executor_pool is None: @@ -1770,17 +1772,11 @@ class Phase2Translator: bidx, rel_first, bcount = futures[future] try: batch_errors, batch, per_file_times = future.result() - for src, elapsed, rel in per_file_times: - done_files += 1 - _vlog().info(f" [{done_files}/{total_files}] {rel} ({elapsed:.1f}s)") - for src, err in batch_errors: - rel = os.path.relpath(src, self.src_root) - _vlog().error(f" {rel}: {err}") - errors.append((rel, err)) - _vlog().info(f" [批次完成] {bcount} 文件, 首个 {rel_first}") + except ReportedCompileError: + raise except Exception as e: - # fail-fast:worker 已 os._exit(文件编译出错)或进程池 - # 已 broken → 立即取消全部剩余批次并终止编译,不空等。 + # fail-fast:进程池已 broken(worker 异常退出)→ 取消 + # 全部剩余批次并终止编译,不空等。 _vlog().error(f" 批次 {bidx} 异常(worker 已终止): {e}") for fut in futures: if not fut.done(): @@ -1788,8 +1784,26 @@ class Phase2Translator: if self._executor_pool is not None: self._executor_pool.shutdown(wait=False, cancel_futures=True) self._executor_pool = None - raise RuntimeError( - f"批次 {bidx} worker 异常终止,编译立即停止: {e}") + raise ReportedCompileError( + f"批次 {bidx} worker 异常终止,编译立即停止") from None + if batch_errors: + # worker 只回传错误、不写 stderr:完整错误(含源码定位) + # 只在这里输出一次,随后立即终止(fail-fast)。 + src, err = batch_errors[0] + rel = os.path.relpath(src, self.src_root) if src else rel_first + _vlog().error(f"\n文件翻译失败: {rel}\n{err}") + for fut in futures: + if not fut.done(): + fut.cancel() + if self._executor_pool is not None: + self._executor_pool.shutdown(wait=False, cancel_futures=True) + self._executor_pool = None + raise ReportedCompileError( + f"{rel} 翻译失败,编译立即停止") from None + for src, elapsed, rel in per_file_times: + done_files += 1 + _vlog().info(f" [{done_files}/{total_files}] {rel} ({elapsed:.1f}s)") + _vlog().info(f" [批次完成] {bcount} 文件, 首个 {rel_first}") except Exception: # 异常时立即清理,正常流程不 shutdown(留给 includes 阶段复用) if self._executor_pool is not None: @@ -1797,11 +1811,6 @@ class Phase2Translator: self._executor_pool = None raise - if errors: - _vlog().error(f"\n{len(errors)} 个文件翻译失败,立即终止编译") - for rel, err in errors: - _vlog().error(f" {rel}: {err}") - raise RuntimeError(f"{len(errors)} 个文件翻译失败,已终止编译") else: for idx, (i, src_path, out_path, sha1, msm) in enumerate(need_translate): rel = os.path.relpath(src_path, self.src_root) @@ -1811,9 +1820,10 @@ class Phase2Translator: t1 = time.time() _vlog().info(f" [{idx+1}/{len(need_translate)}] {rel} ({t1-t0:.1f}s)") except Exception as e: - _vlog().error(f" {rel}: {e}") - traceback.print_exc() - raise RuntimeError(f"翻译 {rel} 失败,已终止编译: {e}") from e + # 单点输出:完整错误(含源码定位)只打印这一次 + _vlog().error(f"\n文件翻译失败: {rel}\n{type(e).__name__}: {e}") + raise ReportedCompileError( + f"翻译 {rel} 失败,已终止编译") from None t_end = time.time() _vlog().info(f" 翻译总耗时: {t_end-t_start:.1f}s") @@ -3841,13 +3851,8 @@ class Phase2Translator: done_count += 1 try: status, _, err = future.result() - if status == 'ok': - _vlog().info(f" [{done_count}/{len(need_translate)}] 翻译完成: {module_name}.py") - else: - # fail-fast:文件编译出错立即终止(worker 已 os._exit, - # 此处兜底处理残留的 error 返回) - raise RuntimeError( - f"include 翻译失败,立即终止: {module_name}.py: {err}") + except ReportedCompileError: + raise except Exception as e: _vlog().error(f" {module_name}.py: {e}") for f2 in in_progress: @@ -3855,8 +3860,21 @@ class Phase2Translator: if self._executor_pool is not None: self._executor_pool.shutdown(wait=False, cancel_futures=True) self._executor_pool = None - raise RuntimeError( - f"include worker 异常终止,编译立即停止: {e}") + raise ReportedCompileError( + "include worker 异常终止,编译立即停止") from None + if status == 'ok': + _vlog().info(f" [{done_count}/{len(need_translate)}] 翻译完成: {module_name}.py") + else: + # worker 只回传错误、不写 stderr:完整错误(含源码定位) + # 只在这里输出一次,随后立即终止(fail-fast)。 + _vlog().error(f"\n文件翻译失败: {module_name}.py\n{err}") + for f2 in in_progress: + f2.cancel() + if self._executor_pool is not None: + self._executor_pool.shutdown(wait=False, cancel_futures=True) + self._executor_pool = None + raise ReportedCompileError( + "include 翻译失败,编译立即停止") from None except Exception: if self._executor_pool is not None: self._executor_pool.shutdown(wait=False, cancel_futures=True) @@ -3871,12 +3889,24 @@ class Phase2Translator: for item in need_translate: src_path, sha1, module_name, ll_path, obj_path, precompiled_obj = item _vlog().info(f" 翻译: {module_name}.py -> {sha1}.ll") - self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map, dwarf_enabled=self.traceback_enabled) + try: + self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map, dwarf_enabled=self.traceback_enabled) + except Exception as e: + # 单点输出:完整错误(含源码定位)只打印这一次 + _vlog().error(f"\n文件翻译失败: {module_name}.py\n{type(e).__name__}: {e}") + raise ReportedCompileError( + "include 翻译失败,编译立即停止") from None else: item = need_translate[0] src_path, sha1, module_name, ll_path, obj_path, precompiled_obj = item _vlog().info(f" 翻译: {module_name}.py -> {sha1}.ll") - self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map, dwarf_enabled=self.traceback_enabled) + try: + self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map, dwarf_enabled=self.traceback_enabled) + except Exception as e: + # 单点输出:完整错误(含源码定位)只打印这一次 + _vlog().error(f"\n文件翻译失败: {module_name}.py\n{type(e).__name__}: {e}") + raise ReportedCompileError( + "include 翻译失败,编译立即停止") from None # ========== 阶段2:串行后处理(dso_local + stub_decls 注入)========== compile_tasks = [] # [(dso_ll_path, obj_path, src_path, sha1, module_name, ll_path, precompiled_obj, ll_content)] diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 2e7eafb..24083be 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -235,6 +235,110 @@ class ClassHandle(BaseHandle): tn_bare_cls: str = tn.split('.')[-1] if '.' in tn else tn if self._HasClassDefinition(tn_bare_cls, Gen): class_type_names.add(tn_bare_cls) + # 特化 AST:复制模板 → 清空 type_params → 改名为特化名,再整体替换 + # T(注解 + 方法体)。之后走与普通类完全相同的 _EmitClassLlvm 发射 + # (declare_only=False 时逐方法 _EmitFunctionLlvm 生成方法体)。 + SpecNode: ast.ClassDef = copy.deepcopy(Node) + SpecNode.type_params = [] + SpecNode.name = spec_name + for item in SpecNode.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + if item.annotation: + item.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(item.annotation, type_map, cptr_params) + elif isinstance(item, ast.FunctionDef): + for arg in item.args.args: + if arg.annotation: + arg.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(arg.annotation, type_map, cptr_params) + # class 类型参数加指针语义。T 替换后的真实形态可能是 + # Attribute 链('.GNode' → Name('').GNode, + # 见 _make_replacement_node/_make_name_node),不是 ast.Name, + # 故按裸名判据(_BareClassAnnotationName)判定;已经是指针 + # 下标(CPtr[T] / rawptr[T])的注解返回 None,不重复加层。 + raw_name: str | None = self._BareClassAnnotationName(arg.annotation) + if raw_name is not None and raw_name in class_type_names: + arg.annotation = ast.Subscript( + value=ast.Name(id='CPtr', ctx=ast.Load()), + slice=arg.annotation, + ctx=ast.Load(), + ) + if item.returns: + item.returns = self.Trans.FunctionHandler._replace_type_in_annotation(item.returns, type_map, cptr_params) + # 返回类型也加指针语义(同一裸名判据,形态同上) + raw_name: str | None = self._BareClassAnnotationName(item.returns) + if raw_name is not None and raw_name in class_type_names: + item.returns = ast.Subscript( + value=ast.Name(id='CPtr', ctx=ast.Load()), + slice=item.returns, + ctx=ast.Load(), + ) + self.Trans.FunctionHandler._apply_type_map_to_body(item.body, type_map, cptr_params) + saved_builder: ir.IRBuilder = Gen.builder + saved_func: ir.Function = Gen.func + saved_variables: dict = dict(Gen.variables) if Gen.variables else {} + saved_direct_values: dict = dict(Gen._direct_values) if Gen._direct_values else {} + saved_var_type_info: dict = dict(Gen.var_type_info) if Gen.var_type_info else {} + saved_var_signedness: dict = dict(Gen.var_signedness) if Gen.var_signedness else {} + saved_global_vars: set = set(Gen.global_vars) if Gen.global_vars else set() + saved_var_scopes: list = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] + saved_block: ir.Block | None = None + if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated: + saved_block = Gen.builder.block + # 切换 module_sha1 为泛型模板定义模块的 SHA1, + # 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀, + # 与调用端 _struct_sha1_map 查到的 SHA1 一致。 + template_sha1: str | None = template.get('sha1') + if not template_sha1: + # 模板注册表缺 sha1 时回退到"模板类定义模块"(_struct_sha1_map 即 + # 类名 → 定义模块表,Phase2 从各 .vpi 扫描构建):与声明端 + # DeclarationGenerator._get_type_str 的泛型前缀、调用点 + # Gen._struct_sha1_map[spec_name] 同一条规则源;否则 declare/define + # 两侧前缀分裂(使用方模块 vs 模板模块)→ 跨模块 undefined symbol。 + template_sha1 = Gen._struct_sha1_map.get(ClassName) + saved_gen_sha1: str | None = getattr(Gen, 'module_sha1', None) + saved_trans_sha1: str | None = getattr(self.Trans, '_module_sha1', None) + if template_sha1: + Gen.module_sha1 = template_sha1 + self.Trans._module_sha1 = template_sha1 + try: + self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only) + except BaseException: + # 失败时撤销预注册缓存:否则后续调用会把「特化到一半」当成已完成 + # (declare_only=False),方法体永远不会再补发,错误被伪装成 + # "没有 __len__ 方法 / Undefined method"。异常本身不吞,继续上抛。 + Gen._generic_class_specializations.pop(spec_key, None) + raise + finally: + # 确保 Gen 状态恢复,即使 _EmitClassLlvm 抛出异常(异常本身不吞, + # 由调用方记录到 Gen._generic_spec_error 或直接上抛)。 + Gen.builder = saved_builder + if saved_block is not None and Gen.builder is not None: + Gen.builder.position_at_end(saved_block) + Gen.func = saved_func + Gen.variables = saved_variables + Gen._direct_values = saved_direct_values + Gen.var_type_info = saved_var_type_info + Gen.var_signedness = saved_var_signedness + Gen.global_vars = saved_global_vars + self.Trans.VarScopes = saved_var_scopes + # 恢复原始 module_sha1 + Gen.module_sha1 = saved_gen_sha1 + self.Trans._module_sha1 = saved_trans_sha1 + Gen._generic_class_specializations[spec_key] = (spec_name, declare_only) + # 缓存 type_args/type_names,供后续 declare_only=False 完整特化补发方法体使用 + # (如 _HandleMethodCallLlvm 中发现方法未定义时触发) + if not hasattr(Gen, '_generic_class_spec_type_info'): + Gen._generic_class_spec_type_info = {} + Gen._generic_class_spec_type_info[spec_key] = (list(type_args), list(type_names) if type_names else None) + if not hasattr(self.Trans, '_generic_class_specializations'): + self.Trans._generic_class_specializations = {} + self.Trans._generic_class_specializations[spec_key] = spec_name + # 用模板定义模块的 SHA1 注册到 _struct_sha1_map,与方法定义端一致 + if template_sha1: + Gen._struct_sha1_map[spec_name] = template_sha1 + elif hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1: + Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1 + return spec_name + def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None: """解析基类名称的类型种类 diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 1b1c705..00de038 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -3068,8 +3068,10 @@ class ExprCallHandle(BaseHandle): base_name, cached_type_args, Gen, type_names=cached_type_names, declare_only=False ) - except Exception: - # 失败时恢复 declare_only 标记,避免后续调用跳过补发 + except Exception as _spec_err: + # 不静默吞特化异常:暴露到 Gen._generic_spec_error(Undefined method / + # len 失败时随报文输出),并恢复 declare_only 标记避免后续调用跳过补发。 + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' Gen._generic_class_specializations[spec_key] = (cached_name, True) Gen.builder = _saved_builder Gen.func = _saved_func diff --git a/lib/core/Handles/HandlesExprUtils.py b/lib/core/Handles/HandlesExprUtils.py index 7d8b087..f7cb924 100644 --- a/lib/core/Handles/HandlesExprUtils.py +++ b/lib/core/Handles/HandlesExprUtils.py @@ -181,8 +181,8 @@ class ExprUtils: # 泛型特化方法尚未生成时,先补发特化 try: self.Trans.ExprCallHandle._try_complete_generic_specialization(ClassName, op_name, Gen) - except Exception: - pass + except Exception as _spec_err: + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' FullMethodName = f'{ClassName}.{op_name}' if not Gen._has_function(FullMethodName): FullMethodName = f'{ClassName}.{op_name}__' @@ -224,8 +224,8 @@ class ExprUtils: # 缓存机制会从 declare_only 升级为完整特化),补发后重新检查 try: self.Trans.ExprCallHandle._try_complete_generic_specialization(best_candidates[0], op_name, Gen) - except Exception: - pass + except Exception as _spec_err: + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' _fn2: str = f'{best_candidates[0]}.{op_name}' if Gen._has_function(f'{best_candidates[0]}.{op_name}') else f'{best_candidates[0]}.{op_name}__' _f2: Any = Gen._get_function(_fn2) if _f2 is not None and getattr(_f2, 'blocks', []): diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index 0a5465b..87d1d71 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -591,8 +591,14 @@ class FunctionHandle(BaseHandle): # 避免过早触发完整特化(此时 MemManager.alloc 可能尚未注册, # 导致 __new__ 的 pool.alloc(48) 解析失败,IR 块未终止)。 # 完整特化由后续类实例化(L3688/L3753)触发 declare_only=False。 - spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( - ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) + try: + spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( + ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) + except Exception as _spec_err: + # 不静默吞特化异常:记录到 Gen._generic_spec_error 后再 + # 交给外层返回类型回退(否则只剩一个错误的 CInt 返回类型)。 + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' + raise if spec_name2 and spec_name2 in Gen.structs: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2) @@ -995,30 +1001,29 @@ class FunctionHandle(BaseHandle): elif isinstance(node.func, ast.Attribute): if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map: replacement: str = type_map[node.func.value.id] - # 指针类型参数(如 list[CPtr[AST]] 中的 T)在表达式上下文中 - # 需替换为 `CPtr[AST]` 下标,使 __sizeof__ 等处理器能正确识别 - # 指针语义并直接返回 8,避免触发 struct 加载和重入编译 + # 指针类型参数(如 list[CPtr[AST]] 中的 T):表达式里 T 的唯一 + # 用法是 `T.__sizeof__()`,指针大小恒为 8。替换成**裸 CPtr** + # (而不是 CPtr[]):mangled 串含 '.'/'*',既不是 + # 合法 Name,也会让 __sizeof__ 的 Subscript 分支(只认泛型切片) + # 落空后把 CPtr 当变量求值 → "未定义名称: 'CPtr'"。 if cptr_params and node.func.value.id in cptr_params: - node.func.value = ast.Subscript( - value=ast.Name(id='CPtr', ctx=ast.Load()), - slice=self._make_name_node(replacement), - ctx=ast.Load() - ) + node.func.value = ast.Name(id='CPtr', ctx=ast.Load()) else: node.func.value = self._make_name_node(replacement) else: self._apply_type_map_to_expr(node.func.value, type_map, cptr_params) + elif isinstance(node.func, ast.Subscript): + # `T*(expr)` / `list[T](...)`:被调者/转换目标的切片也要替换。 + self._apply_type_map_to_expr(node.func, type_map, cptr_params) for arg in node.args: self._apply_type_map_to_expr(arg, type_map, cptr_params) elif isinstance(node, ast.Attribute): if isinstance(node.value, ast.Name) and node.value.id in type_map: replacement: str = type_map[node.value.id] if cptr_params and node.value.id in cptr_params: - node.value = ast.Subscript( - value=ast.Name(id='CPtr', ctx=ast.Load()), - slice=self._make_name_node(replacement), - ctx=ast.Load() - ) + # 同上:指针类型参数的表达式用法(T.__sizeof__ 等)只需 + # "指针语义",裸 CPtr 即指针大小 8;不要拼 mangled 串。 + node.value = ast.Name(id='CPtr', ctx=ast.Load()) else: node.value = ast.Name(id=replacement, ctx=ast.Load()) else: @@ -1041,7 +1046,14 @@ class FunctionHandle(BaseHandle): self._apply_type_map_to_expr(node.orelse, type_map, cptr_params) elif isinstance(node, ast.Subscript): self._apply_type_map_to_expr(node.value, type_map, cptr_params) - self._apply_type_map_to_expr(node.slice, type_map, cptr_params) + # `T*(expr)` 的指针转换在 AST 里是 Call(func=Subscript(CPtr, T)): + # 切片上的 T 必须整体替换成 `_make_replacement_node` 的产物(如 + # CPtr[.AST]),不能走 Name 分支直接改 id(mangled 串含 '.'/'*' + # 不是合法标识符),否则会留下裸 T → 生成幻影结构体 %".T"。 + if isinstance(node.slice, ast.Name) and node.slice.id in type_map: + node.slice = self._make_replacement_node(type_map[node.slice.id]) + else: + self._apply_type_map_to_expr(node.slice, type_map, cptr_params) elif isinstance(node, ast.Name): if node.id in type_map: node.id = type_map[node.id] @@ -1504,8 +1516,14 @@ class FunctionHandle(BaseHandle): # 返回类型解析只需 struct 定义,不需方法体;使用 declare_only=True # 避免过早触发完整特化(此时 MemManager.alloc 可能尚未注册, # 导致 __new__ 的 pool.alloc(48) 解析失败,IR 块未终止)。 - spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( - ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) + try: + spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( + ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True) + except Exception as _spec_err: + # 不静默吞特化异常:记录到 Gen._generic_spec_error 后再 + # 交给外层返回类型回退(否则只剩一个错误的 CInt 返回类型)。 + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' + raise if spec_name2 and spec_name2 in Gen.structs: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2) diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index d16f0eb..0108220 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -4256,7 +4256,10 @@ class ImportHandle(BaseHandle): gc_spec: str | None = self.Trans.ClassHandler._specialize_generic_class( gc_base, gc_type_args, Gen, type_names=gc_type_names, declare_only=True) - except Exception: + except Exception as _spec_err: + # 不静默吞特化异常:记录现场,供后续 Undefined method / + # len 失败路径把真因带进报错。 + Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}' gc_spec = None Gen.module_sha1 = saved_module_sha1 self.Trans._module_sha1 = saved_trans_sha1 diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index ee75991..03b7867 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -4,7 +4,8 @@ if TYPE_CHECKING: from lib.core.translator import Translator from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo from lib.core.SymbolUtils import ( - IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode) + IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, + MangleTypeArgByRegistry) from lib.core import TypeSystem import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib) import vast as ast @@ -67,7 +68,7 @@ class HandlesTypeMerge(BaseHandle): Line: int = getattr(Node, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") Result = self._GetCTypeInfoInternal(Node) if isinstance(Result, CTypeInfo): Info = Result @@ -83,7 +84,7 @@ class HandlesTypeMerge(BaseHandle): Line: int = getattr(Node, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") LineNum = getattr(Node, 'lineno', None) if getattr(self.Trans, 'DebugFile', None): @@ -119,6 +120,9 @@ class HandlesTypeMerge(BaseHandle): Info.BaseType = TypeSystem.CVoid return Info if BuiltinCls == TypeSystem.CPtr: + # 裸 CPtr 仅来自内部类型字符串;源码注解写 CPtr / CPtr[...] + # 已在解析层拒绝(提示改写 T*)。内部 Subscript(CPtr, T) + # 仍由后续 Subscript 分支解析。 Info.PtrCount = 1 Info.BaseType = TypeSystem.CVoid return Info @@ -800,13 +804,18 @@ class HandlesTypeMerge(BaseHandle): arg_parts: list[str] = [] for elt in slice_node.elts: slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(elt) - arg_parts.append(slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(elt)) + _raw_arg: str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(elt) + # 与 _mangle_generic_class_name 同口径(CInt → i32、 + # CFloat64T → f64):否则注解侧拼出 list[CInt], + # 实际特化名却是 list[i32] → 同名结构体分裂。 + arg_parts.append(MangleTypeArgByRegistry(_raw_arg)) # 必须用 '][' 分隔以匹配 _mangle_generic_class_name 的格式 # (class_name + '[' + ']['.join(mangled_args) + ']') type_arg_str = ']['.join(arg_parts) else: slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node) - type_arg_str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node) + _raw_arg = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node) + type_arg_str = MangleTypeArgByRegistry(_raw_arg) full_spec_name: str = f'{value_node.id}[{type_arg_str}]' ResultInfo.BaseType = TypeSystem.CStruct(name=full_spec_name) ResultInfo.Name = full_spec_name @@ -915,4 +924,4 @@ class HandlesTypeMerge(BaseHandle): Line: int = getattr(Node, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") diff --git a/lib/core/SymbolUtils.py b/lib/core/SymbolUtils.py index 9ec8875..3d4f7a0 100644 --- a/lib/core/SymbolUtils.py +++ b/lib/core/SymbolUtils.py @@ -2141,6 +2141,7 @@ _ANNOTATION_MARKER_ALIASES: dict[str, str] = { } # 指针/引用下标的 base 名:注解里出现这些名字即表示"指针层"(等价旧 CPtr 标记)。 +# CPtr 仅作为内部表示(`T*` 脱糖产物);源码写 CPtr[...] 已在解析层拒绝。 _POINTER_SUBSCRIPT_NAMES: frozenset[str] = frozenset({ 'CPtr', 'rawptr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr', }) @@ -2152,7 +2153,7 @@ def RejectTypeUnionAnnotation(node: ast.AST | None) -> None: Line: int = getattr(node, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") def AnnotationContainsMarker(node: ast.AST, MarkerName: str) -> bool: diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index 44d496b..045a84a 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -145,7 +145,7 @@ class TypeAnnotationResolver: Line: int = getattr(Node, 'lineno', 0) or 0 raise TypeError( f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") if isinstance(Node, ast.Constant): Info: CTypeInfo = TypeAnnotationResolver._from_node_constant(Node, SymbolTable) elif isinstance(Node, ast.Name): @@ -575,6 +575,8 @@ class TypeAnnotationResolver: TypeObj = getattr(TypeSystem, TypeName, None) if isinstance(TypeObj, type) and issubclass(TypeObj, TypeSystem.CType) and TypeObj is not TypeSystem.CType: if TypeObj == TypeSystem.CPtr: + # CPtr 名仅来自内部类型字符串(builtins typedef 值等);源码 + # 注解写 CPtr / CPtr[...] 已在解析层拒绝,提示改写为 T*。 Result: CTypeInfo = CTypeInfo() Result.PtrCount = 1 Result.BaseType = TypeSystem.CVoid() @@ -790,6 +792,8 @@ class TypeAnnotationResolver: MarkerName = base.id elif isinstance(base, ast.Attribute): MarkerName = base.attr + # 指针/引用下标:CPtr 仅由 `T*` 脱糖产生(内部表示),源码写 CPtr[...] + # 已在解析层拒绝;rawptr / CRef / CTempRef / CArrayPtr / CAutoPtr 仍可直写。 if MarkerName in ('CPtr', 'rawptr'): SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.slice, SymbolTable) Result: CTypeInfo = CTypeInfo() @@ -980,7 +984,7 @@ class TypeAnnotationResolver: Where: str = f'{File}:{Line}:{Col}' if File else f'第 {Line} 行第 {Col} 列' raise TypeError( f"[TPC] 类型注解不支持模块前缀 \"{FullName}\"({Where})。" - f"请改写为 \"{TypeName}\";指针写 CPtr[T] / rawptr[T]。") + f"请改写为 \"{TypeName}\";指针写 T*(如 int*)/ rawptr[T]。") # 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window if ModulePath: resolved: bool = False diff --git a/lib/vast/ExprParser.py b/lib/vast/ExprParser.py index 9dc42ef..cc883e3 100644 --- a/lib/vast/ExprParser.py +++ b/lib/vast/ExprParser.py @@ -81,6 +81,32 @@ def _HexValOf(ch: str) -> int: return idx if idx < 16 else idx - 6 +def _FindSourceCPtr(Node: N.AST) -> N.AST | None: + """在注解 AST 中查找**源码书写**的 `CPtr`(裸名 / 限定名)。 + + 内部表示仍是 `Subscript(Name('CPtr'), T)`(`T*` 脱糖产物),但该合成 + Name 不带位置属性;源码中的 CPtr 一定带 lineno。据此只拒绝用户源码写法, + 不影响内部 AST。 + """ + if isinstance(Node, (N.Name, N.Attribute)): + Name: str = Node.id if isinstance(Node, N.Name) else Node.attr + if Name == 'CPtr' and hasattr(Node, 'lineno'): + return Node + for Field in getattr(Node, '_fields', ()): + Value = getattr(Node, Field, None) + if isinstance(Value, N.AST): + Found: N.AST | None = _FindSourceCPtr(Value) + if Found is not None: + return Found + elif isinstance(Value, list): + for Item in Value: + if isinstance(Item, N.AST): + Found = _FindSourceCPtr(Item) + if Found is not None: + return Found + return None + + def _HexEscapeVal(body: str, start: int, count: int) -> int: """取转义序列后 count 位十六进制的值(越界位置与非十六进制字符均按 0 计)。 @@ -1710,9 +1736,13 @@ class ExprParserMixin(TokenStream): 无法解析的后缀形态**响亮失败**(SyntaxError,含 行:列 + 源码片段 + 形态 + 正确写法示例),绝不静默丢弃:注解末尾若仍遗留未被 `_AtPtrSuffix` 接受的 - '*'/'**'(如 `a: int * 2` / `a: int* | CPtr`),判据拒绝消费即终止编译 + '*'/'**'(如 `a: int * 2`),判据拒绝消费即终止编译 (静默退化会产出错误的指针层数)。 + 用户源码不再接受 `CPtr[...]` / `CPtr` 指针写法(TypeError,提示改写成 + `T*`);内部 AST 仍以 `Subscript(Name('CPtr'), T)` 表示指针,`T*` 的 + 脱糖产物不受此限制。 + 值引用参数注解(仅形参位有效):前导 `&` 为 ref 模式、`&temp` 为 temp 模式, 合成 Subscript 形态 `CRef[T]` / `CTempRef[T]`(CRef/CTempRef 非真实类, 仅按名字识别;语义侧见 HandlesFunctions / FuncGen)。表达式位的 `&x` 不受影响。 @@ -1782,6 +1812,13 @@ class ExprParserMixin(TokenStream): raise SyntaxError( "[vast] 类型注解的修饰词后缺少类型(如 `x: const int`)。") return None + SourceCPtr: N.AST | None = _FindSourceCPtr(expr) + if SourceCPtr is not None: + Line: int = getattr(SourceCPtr, 'lineno', 0) or 0 + Col: int = (getattr(SourceCPtr, 'col_offset', 0) or 0) + 1 + raise TypeError( + f"[vast] 源码不支持 CPtr 指针写法(第 {Line} 行第 {Col} 列):" + f"指针请写 T*(如 int*)") if isinstance(expr, N.BinOp) and isinstance(expr.op, N.BitOr): def _is_none_literal(n: N.AST) -> bool: if isinstance(n, N.Constant): @@ -1797,7 +1834,7 @@ class ExprParserMixin(TokenStream): Line: int = getattr(expr, 'lineno', 0) or 0 raise TypeError( f"[vast] 不支持类型联合 'T1 | T2'(第 {Line} 行);" - f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字") + f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字") if self._AtPtrSuffix(expr): expr = self._ConsumePtrSuffix(expr) tok: Token = self._Peek() @@ -1813,10 +1850,9 @@ class ExprParserMixin(TokenStream): f"或其后不是后缀的合法结束位置(注解结尾,或 ']' / ',' / ')' / ':' / '=')。" f"源码片段 {snippet!r}。" f"期望形态:`T*`(1 层)/ `T**`(2 层),T 可为裸名 / X / mod.Type / " - f"rawptr[T] / CPtr[T]。" - f"正确示例:`a: CPtr*` / `a: rawptr*` / `a: X**` / " - f"`a: rawptr[ast.AST*]` / `def f(p: int*) -> int**`。" - ) + f"rawptr[T]。" + f"正确示例:`a: int*` / `a: rawptr*` / `a: X**` / " + f"`a: rawptr[ast.AST*]` / `def f(p: int*) -> int**`。") if ref_mode is not None: expr = self._MakeRefMarker(expr, ref_mode, ref_tok) self._ApplyTypePrefix(expr, markers, attributes, byte_order, bit_width) diff --git a/lib/vast_c/_parser.pyd b/lib/vast_c/_parser.pyd index 76cc98e3d19cb9bfa9fac0c7e1f0627676e10267..61fa0e386ae8ca5b5f16fdc6015d99559866c00e 100644 GIT binary patch delta 64191 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 VNxz~O?0QxILlzuNTokens; I++) { + if (P->Tokens[I].Line == Line && P->Tokens[I].Col == Col) { + return &P->Tokens[I]; + } + } + return NULL; +} + /* 类型注解入口:置注解模式标志(对齐 Python ExprParser._ParseTypeAnnotation)。 * * 值引用参数注解(仅形参位有效,对齐纯 Python 端): @@ -3126,6 +3220,17 @@ static PyObject *ParseTypeAnnotation(Parser *P) { Py_XDECREF(Attributes); return NULL; } + /* 源码不再接受 CPtr[...] / CPtr 指针写法(内部 `T*` 脱糖产物无 lineno)。 */ + PyObject *SourceCPtr = FindSourceCPtr(Node); + if (SourceCPtr != NULL) { + Token *BadTok = FindTokenAt(P, SourceCPtr); + SyntaxErrorAt(P, BadTok != NULL ? BadTok : RefTok, + "指针请写 T*(如 int*):源码不再支持 CPtr[...] 指针写法"); + Py_DECREF(Node); + Py_XDECREF(Markers); + Py_XDECREF(Attributes); + return NULL; + } /* `T | None` / `None | T` 等价于 T;两侧同为 None 或均非 None 仍报错。 * 对齐 Pure Python ExprParser._ParseTypeAnnotation 的联合处理。 */ if (NodeIs(Node, "BinOp")) {