From e7ef23b43254980f93f849cf3e3a3f5983096225 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 4 Nov 2026 22:49:57 +0800 Subject: [PATCH] refactor(types): drop retired t/c module type spellings The `t`/`c` modules are gone, so their C type aliases (CInt*, CUnsigned*, CSizeT, CBool, CVoid, CFloat, CDouble, CChar, t.State, t.DefineT, t.VolatileT, the c.CIf family, @c.CReturn) are no longer recognised or reported anywhere: sign inference, enum widths, stub generation/reading, expression lookups and the LSP type-alias check. `import t` / `import c` no longer gets a special message. --- App/lib/Phase/Phase1/Phase1Main.vp | 2 +- App/lib/Stub/StubGen/Converter.vp | 46 ++---------- App/lib/Stub/StubGen/VpiReader.vp | 43 +++++------ App/lib/core/Gen/Call/CallGenCtor.vp | 4 +- App/lib/core/Gen/Call/CallGenDispatch.vp | 37 +--------- App/lib/core/Gen/Call/CallGenLeafKit.vp | 2 +- App/lib/core/Gen/Call/CallGenMixin.vp | 6 +- App/lib/core/Gen/Class/ClassGenBase.vp | 71 +++++------------- App/lib/core/Gen/Class/ClassGenEnum.vp | 17 +---- App/lib/core/Gen/Expr/ExprGenAttr.vp | 8 +- App/lib/core/Gen/Expr/ExprGenBase.vp | 22 +++--- App/lib/core/Gen/Expr/ExprGenCdef.vp | 24 ++---- App/lib/core/Gen/Expr/ExprGenConst.vp | 10 +-- App/lib/core/Gen/Expr/ExprGenName.vp | 21 ++---- App/lib/core/Gen/Expr/ExprGenOps.vp | 4 +- App/lib/core/Gen/Func/FuncGenMixin.vp | 16 ++-- App/lib/core/Gen/GenApi.vp | 4 +- App/lib/core/Gen/ImportsGenMixin.vp | 4 - App/lib/core/Gen/StructGenMixin.vp | 4 +- App/lib/core/Gen/Translator.vp | 2 +- App/lib/core/Gen/TranslatorGenMixin.vp | 10 +-- App/lib/core/Gen/Type/TypeGenBase.vp | 2 +- App/lib/core/Gen/Type/TypeGenCType.vp | 6 +- App/lib/core/Gen/Type/TypeGenErr.vp | 8 +- App/lib/core/Gen/Type/TypeSpec.vp | 93 +++++++++--------------- App/lib/core/Gen/VarGenMixin.vp | 14 ++-- App/lib/core/Repl.vp | 2 +- App/lib/lsp/LspSymbols.vp | 5 +- 28 files changed, 161 insertions(+), 326 deletions(-) diff --git a/App/lib/Phase/Phase1/Phase1Main.vp b/App/lib/Phase/Phase1/Phase1Main.vp index 16448f2..b824c08 100644 --- a/App/lib/Phase/Phase1/Phase1Main.vp +++ b/App/lib/Phase/Phase1/Phase1Main.vp @@ -789,7 +789,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogg t_f1: uint64 = win32.win32base.GetTickCount64() # Register TypedefT by scanning source text: AST string fields (attr/id) point into src_buf - # and dangle across phases (reading attr faults), so match "NAME: t.TypedefT = TYPE" lines. + # and dangle across phases (reading attr faults), so match "NAME: TypedefT = TYPE" lines. GenApi.RegisterCTypedefFromSource(mb, src_buf) # Generate the .vpi stub (walk the AST directly). 1b-pre already generated one, so this diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 8087129..d32af02 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -576,9 +576,8 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth: if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(annot) if nm.id is not None: - # Retired bare markers map to their source spellings. + # Bare markers map to their source spellings. if string.strcmp(nm.id, "PtrT") == 0: return _PyiEmit(buf, buf_size, pos, "rawptr") - if string.strcmp(nm.id, "CVoid") == 0: return _PyiEmit(buf, buf_size, pos, "void") return _PyiEmit(buf, buf_size, pos, nm.id) return _PyiEmit(buf, buf_size, pos, "int") @@ -586,7 +585,6 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth: if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(annot) if at.attr is not None and string.strcmp(at.attr, "PtrT") == 0: return _PyiEmit(buf, buf_size, pos, "rawptr") - if at.attr is not None and string.strcmp(at.attr, "CVoid") == 0: return _PyiEmit(buf, buf_size, pos, "void") pos = _PyiTypeStr(buf, buf_size, pos, at.value, depth + 1) pos = _PyiEmit(buf, buf_size, pos, ".") if at.attr is not None: pos = _PyiEmit(buf, buf_size, pos, at.attr) @@ -608,8 +606,8 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth: # Subscript: subscripted type (e.g. list[int], ArrayT[elem, count]) if k == ast.ASTKind.Subscript: sub: ast.Subscript* = ast.Subscript*(annot) - # Builtin markers carry source syntax in a stub: `T*` / `[N]T` / `const T` / - # `volatile T` / `&T` / `&temp T`. The retired t.* C-names must never be written. + # Builtin markers are written as source syntax: `T*` / `[N]T` / `const T` / + # `volatile T` / `&T` / `&temp T`. if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: mk_n: ast.Name* = ast.Name*(sub.value) if mk_n.id is not None: @@ -842,30 +840,6 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet, node: ast.AST*, dept return pos -# _PyiRejectCReturnDecorator - fail if @c.CReturn appears in the decorator list. -# The decorator was removed; a stale stub must be regenerated. 0 = none found. -def _PyiRejectCReturnDecorator(node: ast.AST*, decorators: list[ast.AST*]*) -> int: - """Fail fast on a @c.CReturn decorator (returns 0 when absent)""" - if decorators is None: return 0 - dn: sizet = len(decorators) - di: sizet = 0 - while di < dn: - dnode: ast.AST* = decorators.get(di) - di += 1 - if dnode is None: continue - # Handles both @c.CReturn(...) (Call with func=Attribute) and bare @c.CReturn - dattr: ast.Attribute* = None - if dnode.kind() == ast.ASTKind.Call: - dcall: ast.Call* = ast.Call*(dnode) - if dcall.func is not None and dcall.func.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dcall.func) - elif dnode.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dnode) - if dattr is None or dattr.attr is None: continue - if string.strcmp(dattr.attr, "CReturn") == 0: - GenApi.fatal_error(node, "vpi still contains `@c.CReturn` (removed): regenerate the .vpi using a return annotation `-> tuple[ty1, ty2, ...]` (you may add --clean)", "TypeError") - return 1 - return 0 - - # ============================================================ # 逃逸摘要计算用的复用临时区(74 槽:gset[0]=global 计数、gset[1..65)=名哈希、box=gset+65)。 # 只分配一次,避免每个 def 都分配;布局与 StructGen 的 EscScratch 完全一致。 @@ -1024,9 +998,6 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet, fn: ast.FunctionDef*, if ret_node is not None: pos = _PyiEmit(buf, buf_size, pos, " -> ") pos = _PyiTypeStr(buf, buf_size, pos, ret_node) - else: - # Without a `->` annotation, @c.CReturn is removed: fail fast to regenerate vpi - _PyiRejectCReturnDecorator(fn, fn.decorator_list) pos = _PyiEmit(buf, buf_size, pos, ": pass") # v3 跨模块逃逸摘要:把形参逃逸掩码与返回借用位写成**同一行**的行尾注释,供 VpiReader @@ -1322,7 +1293,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf if tree.children is not None: pre_children: list[ast.AST*]* = tree.children pcn: sizet = len(pre_children) - # Pass 1: count t.DefineT declarations (C arrays need a fixed size first) + # Pass 1: count DefineT declarations (C arrays need a fixed size first) _g_pyi_cdef_count = 0 for pci0 in range(int(pcn)): stmt_pc0: ast.AST* = pre_children.get(pci0) @@ -1373,7 +1344,6 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf tree_children: list[ast.AST*]* = tree.children n: sizet = len(tree_children) - # t / c are retired compiler-internal modules: the stub never injects their imports. pos = _PyiEmit(buf, buf_size, pos, "\n") # Pass 2: emit declarations @@ -1461,8 +1431,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf if aa.target is not None and aa.target.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(aa.target) if nm.id is not None: - # Retired t.TypedefT / t.DefineT markers are written as their source - # syntax (`typedef NAME = T` / `define NAME[: T] = value`). + # TypedefT / DefineT markers are written as source syntax: + # `typedef NAME = T` / `define NAME[: T] = value`. is_ctypedef_ann: int = 0 if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Name: ctd_nm0: ast.Name* = ast.Name*(aa.annotation) @@ -1560,7 +1530,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf viperlib.snprintf(num_buf_u, 32, " = %lld", neg_val) pos = _PyiEmit(buf, buf_size, pos, num_buf_u) elif aa.value is not None and aa.value.kind() == ast.ASTKind.Call: - # Type-constructor constant (e.g. t.CUnsignedLong(-11)): + # Type-constructor constant (e.g. uint32(-11)): # extract and emit the integer value of the first argument. call_cv: ast.Call* = ast.Call*(aa.value) if call_cv.args is not None: @@ -1600,7 +1570,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf viperlib.snprintf(fbuf_cu, 64, " = %.17g", neg_cf) pos = _PyiEmit(buf, buf_size, pos, fbuf_cu) elif arg_kind == ast.ASTKind.BinOp: - # BinOp inside a Call (e.g. t.CUnsignedLong(A | B)): + # BinOp inside a Call (e.g. uint32(A | B)): # recursively evaluate the BinOp value. binop_val_bo: int64 = _eval_binop_int(first_arg) num_buf_bo: bytes = mb.alloc(32) diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index e287cea..15ab667 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -2124,21 +2124,18 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m if tup_head_t is None: return None return mlirlite.Struct(pool, tup_head_t, tup_count_t, None) - # Pure marker annotations (t.State / t.ExternT / t.ExportT alone, optional t./c. prefix) - # -> void: decorator markers, not real return types, matching _inject_module_declare. + # Pure marker annotations (State / ExternT / ExportT alone) mean void. marker_len: sizet = string.strlen(ret_annot) mk_s: sizet = 0 while mk_s < marker_len and ret_annot[mk_s] == ' ': mk_s += 1 mk_e: sizet = marker_len while mk_e > mk_s and ret_annot[mk_e - 1] == ' ': mk_e -= 1 - mk_off_m: sizet = 0 - if mk_e - mk_s >= 2 and (ret_annot[mk_s] == 't' or ret_annot[mk_s] == 'c') and ret_annot[mk_s + 1] == '.': mk_off_m = 2 - mk_nlen: sizet = mk_e - mk_s - mk_off_m - if (mk_nlen == 5 and string.strncmp(ret_annot + mk_s + mk_off_m, "State", 5) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "ExternT", 7) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s + mk_off_m, "ExportT", 7) == 0): + mk_nlen: sizet = mk_e - mk_s + if (mk_nlen == 5 and string.strncmp(ret_annot + mk_s, "State", 5) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s, "ExternT", 7) == 0) or (mk_nlen == 7 and string.strncmp(ret_annot + mk_s, "ExportT", 7) == 0): return mlirlite.Void(pool) - # Unions were retired, so a stub return annotation is a single type. `T*` / `T**` and - # `const` / `volatile` prefixes are handled by the shared single-segment resolver. + # A stub return annotation is a single type. `T*` / `T**` and `const` / `volatile` + # prefixes are handled by the shared single-segment resolver. return _resolve_single_vpi_type_str(pool, ret_annot) @@ -2372,8 +2369,6 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp while pos < total_len and import_mods[pos] != ' ': pos += 1 m_len: sizet = pos - m_start if m_len == 0: continue - # t/c built-in libs are not compiled, so they have no vpi stub - if m_len == 1 and (import_mods[m_start] == 't' or import_mods[m_start] == 'c'): continue mod_buf: bytes = stdlib.malloc(m_len + 1) if mod_buf is None: continue string.strncpy(mod_buf, import_mods + m_start, m_len) @@ -3268,7 +3263,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v n: sizet = len(ch) # Collect the read module's own imports from the stub to build an isolated annotation - # context, replacing the current module's imports (e.g. t.ArrayT[str] needs 't' imported). + # context that replaces the current module's imports. stub_imported_modules: str = None stub_from_imports: str = None # Bookkeeping goes through StubMergerStore (same as ImportsGenMixin.translate_import): @@ -3508,7 +3503,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v _inject_function_declare(pool, mod, fd, trans, src_sha1, imported_modules, from_imports, i32_ty, i8_ptr_ty, funcs_ptr, max_funcs) continue - # AnnAssign with t.TypedefT -> register TypedefT; + # AnnAssign with TypedefT -> register TypedefT; # plain module-level globals (e.g. tokens._op_head) -> external global declare if kd == ast.ASTKind.AnnAssign: aa: ast.AnnAssign* = ast.AnnAssign*(child) @@ -3561,7 +3556,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v # `define X = None`: a named None (see _register_cdefine_from_value). GenApi.register_cdefine_string(pool, cdef_tgt.id, "None", def_mod) elif cdef_is_str == 0 and cdef_is_float != 0: - # Float DefineT (e.g. FRAGMENTATION_THRESHOLD: t.DefineT = 0.7): register via + # Float DefineT (e.g. FRAGMENTATION_THRESHOLD: DefineT = 0.7): register via # register_cdefine_double (integer extraction would fail fast). # 注解声明 float 时带上 f32 种类(与定义方同一套裁决)。 GenApi.register_cdefine_double(pool, cdef_tgt.id, cdef_float_val, GenApi.cdefine_decl_float_bits(pool, aa.annotation), def_mod) @@ -3695,7 +3690,7 @@ def _vpi_tattr_name(node: ast.AST*, attr_name: str) -> int: def _vpi_class_has_packed(decorator_list: list[ast.AST*]*) -> int: - """Check whether a vpi ClassDef decorator list contains t.attr.packed.""" + """Check whether a vpi ClassDef decorator list contains attr.packed.""" if decorator_list is None: return 0 dn: sizet = len(decorator_list) if dn == 0: return 0 @@ -3718,7 +3713,7 @@ def _vpi_class_has_packed(decorator_list: list[ast.AST*]*) -> int: def _vpi_class_is_renum(class_cd: ast.ClassDef*) -> int: - """Check whether a vpi ClassDef is a REnum (base class contains t.REnum); 1=yes / 0=no.""" + """Check whether a vpi ClassDef is a REnum (base class contains REnum); 1=yes / 0=no.""" if class_cd is None or class_cd.bases is None: return 0 bases: list[ast.AST*]* = class_cd.bases bn: sizet = len(bases) @@ -3935,7 +3930,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul field_types_buf: sizet* = pool.alloc(8 * GenTypes.FIELD_MAX) # Per-field marker buffers, index-aligned with field_names_buf / add_field order. The .vpi text # keeps each field's raw annotation (Converter._PyiTypeStr renders BinOp/Attribute verbatim, so - # `X | t.BigEndian` / `t.VolatileT | int` survive), so the same markers ClassGenDef extracts on + # `X | bigend` / `volatile | int` survive), so the same markers ClassGenDef extracts on # the definition side must be re-extracted here; otherwise a struct referenced across a module # boundary loses its volatile/const/byte-order semantics and the same field compiles differently # per module (the bug this fixes). @@ -3980,8 +3975,8 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul if GenApi.has_decorator_marker(annot_fc, "VolatileT", 0) != 0: field_volatile_buf[field_count] = 1 if GenApi.has_pointee_volatile_marker(annot_fc) != 0: field_pointee_volatile_buf[field_count] = 1 if GenApi.is_const_object_marker(annot_fc, field_ty_c) != 0: field_const_buf[field_count] = 1 - # Byte order: 1 = t.BigEndian / 2 = t.LittleEndian (0 stays native); - # annotation `|` means "and", so `X | t.BigEndian` is a BigEndian X. + # Byte order: 1 = bigend / 2 = littlend (0 stays native); + # annotation `|` means "and", so `X | bigend` is a BigEndian X. if GenApi.has_decorator_marker(annot_fc, "BigEndian", 0) != 0: field_byteorder_buf[field_count] = 1 elif GenApi.has_decorator_marker(annot_fc, "LittleEndian", 0) != 0: field_byteorder_buf[field_count] = 2 field_count += 1 @@ -4203,17 +4198,17 @@ def _inject_function_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, has_extern: int = 0 has_state: int = 0 has_export: int = 0 - # `extern def` / `export def` recorded as the vpi keyword are the same storage markers as the - # legacy t.ExternT / t.ExportT return annotations: the defining side emits the bare C name, so - # the injected declare must be bare as well (a SHA1 prefix leaves the symbol undefined). + # `extern def` / `export def` keywords and ExternT / ExportT return annotations are the same + # storage markers: the defining side emits the bare C name, so the injected declare must be + # bare as well (a SHA1 prefix leaves the symbol undefined). if (fd.flags & ast.FLAG_IS_EXTERN) != 0: has_extern = 1 if (fd.flags & ast.FLAG_IS_EXPORT) != 0: has_export = 1 if fd.returns is not None: if GenApi.has_decorator_marker(fd.returns, "ExternT") != 0: has_extern = 1 if GenApi.has_decorator_marker(fd.returns, "State") != 0: has_state = 1 if GenApi.has_decorator_marker(fd.returns, "ExportT") != 0: has_export = 1 - # Bare-struct param rule (see _AggregateParamTy): C ABI externs (t.ExternT/t.State) by value; - # the rest (incl. t.ExportT) keep Ptr(struct). Same source as FuncGenDef.is_extern_decl. + # Bare-struct param rule (see _AggregateParamTy): C ABI externs (ExternT/State) by value; + # the rest (including ExportT) keep Ptr(struct). Same source as FuncGenDef.is_extern_decl. agg_is_c_abi: int = 0 if has_extern != 0 or has_state != 0: agg_is_c_abi = 1 @@ -4527,7 +4522,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_ # _register_ctypedef_from_annassign - register a TypedefT from an AnnAssign node. -# Extracts the NAME and type expression from `NAME: t.TypedefT = Type` and registers it. +# Extracts the NAME and type expression from `NAME: TypedefT = Type` and registers it. def _register_ctypedef_from_annassign(pool: memhub.MemBuddy*, aa: ast.AnnAssign*) -> None: """Extract and register a TypedefT from an AnnAssign node.""" if aa is None or pool is None: return diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 45a1af9..e02a556 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -922,7 +922,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if self.Gen.ExprGenBase._zext_or_sext_val(pool, val, src_node, trans) != 0: return mlirlite.build_zext(builder, val, target_ty) return mlirlite.build_sext(builder, val, target_ty) else: - # Target i1 (bool / t.CBool) via an EXPLICIT cast `t.CBool(x)` / `(bool)(x)`: + # Target i1 (bool / bool) via an EXPLICIT cast `bool(x)` / `(bool)(x)`: # normalise truth as `x != 0 -> 1/0` (not trunc, which would make x=2 false while # `if 2:` is true). Implicit wide-int -> bool stores no longer normalise here; they # fail fast in coerce_to_type (rule 2026-10-13), so only explicit casts reach this. @@ -1018,7 +1018,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): if cn.const_kind == ast.CONST_CHAR: return "char" if cn.const_kind == ast.CONST_STR: return "str" return "int" - # type-cast call: int(...)/float(...)/t.CDouble(...) + # type-cast call: int(...)/float(...)/double(...) if k == ast.ASTKind.Call: cl_f: ast.Call* = ast.Call*(arg_node) if cl_f.func is not None: diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index 877c32f..067e6c1 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -233,33 +233,14 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): def _tc_h2_c_special(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: char*, cargs: list[ast.AST*]*, can: sizet, hit_box: rawptr = None) -> mlirlite.Value*: """Special __asm__/__llvmir__ calls; marks hit_box for void calls, else returns None.""" - # Retired c.* pointer builtins: fail fast with the replacement syntax. - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - ra_c: ast.Attribute* = ast.Attribute*(cl.func) - if ra_c.value is not None and ra_c.value.kind() == ast.ASTKind.Name and ra_c.attr is not None: - rn_c: ast.Name* = ast.Name*(ra_c.value) - if rn_c.id is not None and string.strcmp(rn_c.id, "c") == 0: - if string.strcmp(ra_c.attr, "Deref") == 0 or string.strcmp(ra_c.attr, "DerefAs") == 0 \ - or string.strcmp(ra_c.attr, "Set") == 0 or string.strcmp(ra_c.attr, "Addr") == 0 \ - or string.strcmp(ra_c.attr, "Load") == 0: - self.Gen.TypeGenErr.fatal_error(cl, f"c.{ra_c.attr} was removed; use `*p` (read), `*p = v` (write) or `&v` (address-of)", "NameError") - return None - # __asm__(...) / __llvmir__(...) sugar: bare calls equal c.Asm(...) / c.LLVMIR(...). Must - # intercept before the c.* attribute branch, since the bare cl.func is a Name. + # __asm__(...) / __llvmir__(...) sugar: intercept bare calls before the module path. if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name: bare_nm: ast.Name* = ast.Name*(cl.func) - if bare_nm.id is not None and (string.strcmp(bare_nm.id, "Deref") == 0 or string.strcmp(bare_nm.id, "DerefAs") == 0): - self.Gen.TypeGenErr.fatal_error(cl, f"{bare_nm.id} was removed; use `*p` (read), `*p = v` (write) or `&v` (address-of)", "NameError") - return None if bare_nm.id is not None and string.strcmp(bare_nm.id, "defined") == 0: # defined(NAME) is a compile-time predicate valid only inside a cif/celif condition; # it is evaluated there and never lowered as a runtime call. self.Gen.TypeGenErr.fatal_error(cl, "defined(NAME) is only valid inside a cif/celif condition; it cannot be used in a normal expression", "NameError") return None - if bare_nm.id is not None and (string.strcmp(bare_nm.id, "CIf") == 0 or string.strcmp(bare_nm.id, "CIfdef") == 0 or string.strcmp(bare_nm.id, "CIfndef") == 0 or string.strcmp(bare_nm.id, "CElif") == 0 or string.strcmp(bare_nm.id, "CElse") == 0 or string.strcmp(bare_nm.id, "CEndif") == 0): - # removed spellings (also covered for the bare-name form of the c.CIf family) - self.Gen.TypeGenErr.fatal_error(cl, "c.CIf/c.CIfdef/c.CIfndef/c.CElif/c.CElse/c.CEndif were removed; use the cif/celif/celse statements and the defined(NAME) predicate instead (e.g. `cif defined(NAME):` ... `celse:` ...)", "NameError") - return None if bare_nm.id is not None and string.strcmp(bare_nm.id, "__asm__") == 0: # translate_c_asm returns None for void output: set the hit flag so translate_call # does not misread it as a miss and fall through to the external function path. @@ -447,7 +428,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): bare_arg2_bn: ast.Name* = ast.Name*(bare_arg2_node) if bare_arg2_bn.id is not None and (string.strcmp(bare_arg2_bn.id, "PtrT") == 0 or string.strcmp(bare_arg2_bn.id, "rawptr") == 0): bare_arg2_is_cptr = 1 if bare_arg2_is_cptr != 0: - # CVoid* -> i8* (void* is represented as i8* in LLVM) + # void* -> i8* (void* is represented as i8* in LLVM) match bare_ty: case mlirlite.LLVMType.Void(): bare_ty = mlirlite.Int8(pool) @@ -553,17 +534,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if string.strcmp(sz_cls_name, "int") == 0: sz_builtin = 4 elif string.strcmp(sz_cls_name, "str") == 0: sz_builtin = 8 elif string.strcmp(sz_cls_name, "bytes") == 0: sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CInt") == 0: sz_builtin = 4 - elif string.strcmp(sz_cls_name, "CInt8T") == 0: sz_builtin = 1 - elif string.strcmp(sz_cls_name, "CInt16T") == 0: sz_builtin = 2 - elif string.strcmp(sz_cls_name, "CInt32T") == 0: sz_builtin = 4 - elif string.strcmp(sz_cls_name, "CInt64T") == 0: sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CChar") == 0: sz_builtin = 1 - elif string.strcmp(sz_cls_name, "CDouble") == 0: sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CFloat") == 0: sz_builtin = 4 elif string.strcmp(sz_cls_name, "PtrT") == 0: sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CSizeT") == 0: sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CBool") == 0: sz_builtin = 1 elif string.strcmp(sz_cls_name, "bool") == 0: sz_builtin = 1 # Bare builtin names resolved from generic T (e.g. T->"double"/"float"): without # them sz_builtin stays -1 and Name(T) is translated as a value, causing NameError. @@ -748,7 +719,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.build_call(builder, len_mangled_x, len_self_x, 1, len_ret_x, 0) # fail-fast: the class has no __len__ (compile-time error, matching TPC # HandlesExprBuiltin._FailFastLenUnsupported wording). - self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers (t.ArrayT[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError") + self.Gen.TypeGenErr.fatal_error(len_arg_node, f"len() argument type '{len_cls_nm}' has no __len__ method. len() only supports fixed-size arrays/array pointers ([N]T), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError") # Non-struct: char* (Ptr(Int8)) uses strlen; other types fail fast len_arg_ty: mlirlite.LLVMType* = mlirlite.value_get_ty(len_val) len_is_str: int = 0 @@ -781,7 +752,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return mlirlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0) # fail-fast: not a string/array/object, so length is unavailable (matching TPC # HandlesExprBuiltin._FailFastLenUnsupported wording). - self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers (t.ArrayT[T, N]), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError") + self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() argument type not supported (not a string/array/object). len() only supports fixed-size arrays/array pointers ([N]T), i8* (str/bytes), or structs with __len__; non-i8 bare pointers/scalar pointers have no length semantics: use str/bytes for strings, record the length yourself when the element count is needed, or use rawptr[Element] and maintain the element count explicitly", "TypeError") # Detect isinstance(): runtime vtable subclass-set comparison. obj's head vtable pointer must # be in {Cls and all subclass vtables}; NoVTable targets fall back to a compile-time check. diff --git a/App/lib/core/Gen/Call/CallGenLeafKit.vp b/App/lib/core/Gen/Call/CallGenLeafKit.vp index 3d2ed04..c880ccd 100644 --- a/App/lib/core/Gen/Call/CallGenLeafKit.vp +++ b/App/lib/core/Gen/Call/CallGenLeafKit.vp @@ -642,7 +642,7 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin): # 3. build the signature from arg types + registered ret type (missing = fail fast) ret_ty: mlirlite.LLVMType* = self.lookup_func_ptr_ret(func_name) if ret_ty is None: - self.Gen.TypeGenErr.fatal_error(None, f"Return type of function pointer variable '{func_name}' is not registered (t.Callable annotation missing)", "TypeError") + self.Gen.TypeGenErr.fatal_error(None, f"Return type of function pointer variable '{func_name}' is not registered (Callable annotation missing)", "TypeError") ret_ty = i32_ty fp_first: mlirlite.ParamNode* = None fp_prev: mlirlite.ParamNode* = None diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index f383d0f..c652156 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -1168,15 +1168,15 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): # Closure variable (nested function hoisted and registered): extract fn_ptr/env_ptr and call indirectly. if self.Gen.CallGenLeafKit.is_closure_name(func_name) != 0: return self.Gen.CallGenLeafKit.translate_closure_call(pool, builder, mod, fp_alloca, cargs, can, trans) - # Function-pointer variable (t.Callable annotation -> i8** alloca): build the signature from args and call indirectly. + # Function-pointer variable (Callable annotation -> i8** alloca): build the signature from args and call indirectly. if self.Gen.CallGenLeafKit._is_func_ptr_alloca(fp_alloca) != 0: - # Distinguish t.Callable (true function pointer) from rawptr (closure pointer): a rawptr + # Distinguish Callable (true function pointer) from rawptr (closure pointer): a rawptr # holds {fn_ptr, env_ptr} and must pass env, else a direct call jumps into closure data and crashes. ve_fp: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, func_name) is_cptr_annot_fp: int = 0 fp_annot: char* = self.Gen.VarGen.var_annot_class_name(ve_fp) if fp_annot is not None: - # [S4] PtrT marker = annotation base name exactly "PtrT": t.Callable[[A],R] also resolves to + # [S4] PtrT marker = annotation base name exactly "PtrT": Callable[[A],R] also resolves to # Ptr(i8) (same Spec), so only the annotation name can carry the marker; substring matching would misfire. if TSpec.SpecTypeNameBaseIs(fp_annot, "PtrT") != 0: is_cptr_annot_fp = 1 if is_cptr_annot_fp == 0: diff --git a/App/lib/core/Gen/Class/ClassGenBase.vp b/App/lib/core/Gen/Class/ClassGenBase.vp index 9092ba3..0250e98 100644 --- a/App/lib/core/Gen/Class/ClassGenBase.vp +++ b/App/lib/core/Gen/Class/ClassGenBase.vp @@ -127,25 +127,12 @@ novirtual class ClassGenBase: # Methods below migrated in P5-2 from HandlesClassDef.vp; intra-module calls use self. def _is_cenum_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: - """Return 1 if the base node is t.EnumBase, else 0.""" + """Return 1 if the base node is EnumBase, else 0.""" if base_node is None: return 0 - k: int = base_node.kind() - # Name('EnumBase') form (from t import EnumBase). - if k == ast.ASTKind.Name: - nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: return 0 - if string.strcmp(nm.id, "EnumBase") == 0: return 1 - # Alias form: from t import EnumBase as en; class Color(en). - # Resolve the original name (en -> EnumBase) before comparing. - if trans is not None and trans._from_imports is not None: - alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) - if alias_orig is not None: - og_len_ce: sizet = 0 - while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0': og_len_ce += 1 - if og_len_ce == 8 and string.strncmp(alias_orig, "EnumBase", 8) == 0: return 1 - return 0 - # Attribute form was retired together with the t module prefix. - return 0 + if base_node.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(base_node) + if nm.id is None: return 0 + return 1 if string.strcmp(nm.id, "EnumBase") == 0 else 0 def _is_enum_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """Return 1 if the ClassDef is a EnumBase (subclasses t.EnumBase or uses @t.EnumBase).""" if cd is None: return 0 @@ -162,24 +149,12 @@ novirtual class ClassGenBase: if self._is_cenum_base(base_node, trans) == 1: return 1 return 0 def _is_cunion_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: - """Return 1 if the base node is t.UnionBase, else 0.""" + """Return 1 if the base node is UnionBase, else 0.""" if base_node is None: return 0 - k: int = base_node.kind() - # Name('UnionBase') form (from t import UnionBase). - if k == ast.ASTKind.Name: - nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: return 0 - if string.strcmp(nm.id, "UnionBase") == 0: return 1 - # Alias form: from t import UnionBase as un; class Data(un). - if trans is not None and trans._from_imports is not None: - alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) - if alias_orig is not None: - og_len_cu: sizet = 0 - while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0': og_len_cu += 1 - if og_len_cu == 9 and string.strncmp(alias_orig, "UnionBase", 9) == 0: return 1 - return 0 - # Attribute form was retired together with the t module prefix. - return 0 + if base_node.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(base_node) + if nm.id is None: return 0 + return 1 if string.strcmp(nm.id, "UnionBase") == 0 else 0 def _is_union_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """Return 1 if the ClassDef is a UnionBase (subclasses t.UnionBase or uses @t.UnionBase).""" if cd is None: return 0 @@ -196,24 +171,12 @@ novirtual class ClassGenBase: if self._is_cunion_base(base_node, trans) == 1: return 1 return 0 def _is_crenum_base(self, base_node: ast.AST*, trans: HT.Translator* = None) -> int: - """Return 1 if the base node is t.REnum, else 0.""" + """Return 1 if the base node is REnum, else 0.""" if base_node is None: return 0 - k: int = base_node.kind() - # Name('REnum') form (from t import REnum). - if k == ast.ASTKind.Name: - nm: ast.Name* = ast.Name*(base_node) - if nm.id is None: return 0 - if string.strcmp(nm.id, "REnum") == 0: return 1 - # Alias form: from t import REnum as ren; class Opt(ren). - if trans is not None and trans._from_imports is not None: - alias_orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, nm.id) - if alias_orig is not None: - og_len_cr: sizet = 0 - while alias_orig[og_len_cr] != ' ' and alias_orig[og_len_cr] != '\0': og_len_cr += 1 - if og_len_cr == 5 and string.strncmp(alias_orig, "REnum", 5) == 0: return 1 - return 0 - # Attribute form was retired together with the t module prefix. - return 0 + if base_node.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(base_node) + if nm.id is None: return 0 + return 1 if string.strcmp(nm.id, "REnum") == 0 else 0 def _is_renum_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """Return 1 if the ClassDef is a REnum (subclasses t.REnum or uses @t.REnum).""" if cd is None: return 0 @@ -692,13 +655,13 @@ novirtual class ClassGenBase: if trans is not None: _fi_pc = trans._from_imports bname: str = self._get_base_name(base_node, pool, _fi_pc) if bname is not None: - # Resolve base aliases (from t import StructBase as cs -> cs is StructBase). + # Resolve base aliases (from X import StructBase as cs -> cs is StructBase). # Otherwise find_struct("cs") fails and the class is deferred forever. bname = self._resolve_base_alias(bname, trans) if self._is_marker_base(bname) == 0: return bname return None def _resolve_base_alias(self, base_name: str, trans: HT.Translator* = None) -> str: - """Resolve a base alias (from t import StructBase as cs -> base cs is actually StructBase).""" + """Resolve a base alias (from X import StructBase as cs -> base cs is actually StructBase).""" if base_name is None or trans is None or trans._from_imports is None: return base_name orig: str = self.Gen.ImportsGen.lookup_from_import_original(trans._from_imports, base_name) if orig is not None: diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index a5fc9a3..c241f97 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -37,16 +37,12 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # [S4 fail-fast] Attribute missing the member name (corrupt AST); no silent i32 fallback self.Gen.TypeGenErr.fatal_error(ann_node, "enum member type annotation Attribute is missing the member name", "TypeError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) - # t.State -> default i32 if string.strcmp(at.attr, "State") == 0: return mlirlite.Int32(pool) - # [enum bool rule] `t.CBool` and bare `bool` both materialize as 8 bits in enum member annotations, - # else the same member would split into i1 / i8; the global `t.CBool` stays i1 (only enums differ). - if string.strcmp(at.attr, "CBool") == 0: return mlirlite.Int8(pool) - # Other t.CXxx types: unified (TypedefT dynamic table first, fall back to map_builtin_type) + # Other qualified types: resolve through the TypedefT table first. ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr, imported_modules, from_imports) if ty is not None: return ty # [S4 fail-fast] annotated but unresolvable -> no silent i32 fallback - self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: t.{at.attr}", "NameError") + self.Gen.TypeGenErr.fatal_error(ann_node, f"failed to resolve enum member type annotation: {at.attr}", "NameError") return mlirlite.Int32(pool) # unreachable (fatal_error already exited) # Name node: from-import form (State / CInt) @@ -598,16 +594,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): if string.strcmp(type_name, "ptrdifft") == 0: return 8 # Builtin types if string.strcmp(type_name, "int") == 0: return 4 - if string.strcmp(type_name, "CInt") == 0: return 4 - if string.strcmp(type_name, "CInt8T") == 0: return 1 - if string.strcmp(type_name, "CInt16T") == 0: return 2 - if string.strcmp(type_name, "CInt32T") == 0: return 4 - if string.strcmp(type_name, "CInt64T") == 0: return 8 - if string.strcmp(type_name, "CChar") == 0: return 1 - if string.strcmp(type_name, "CDouble") == 0: return 8 - if string.strcmp(type_name, "CFloat") == 0: return 4 if string.strcmp(type_name, "PtrT") == 0: return 8 - if string.strcmp(type_name, "CSizeT") == 0: return 8 if string.strcmp(type_name, "str") == 0: return 8 if string.strcmp(type_name, "bytes") == 0: return 8 if string.strcmp(type_name, "bool") == 0: return 1 diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index 86cc3be..16b48a0 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -608,7 +608,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # if obj_ptr is Ptr(Ptr(Struct)) (the alloca of an X* variable), load to deref and get Ptr(Struct) obj_ptr = self._deref_if_ptr_ptr(builder, obj_ptr) - # rawptr[t.VolatileT | T] base (volatile pointee): loads of fields (p.field) through this pointer carry + # rawptr[volatile | T] base (volatile pointee): loads of fields (p.field) through this pointer carry # volatile. It is 1 only when the base resolves to a VarEntry (Name) / FieldEntry (Attribute), else 0. vol_ba_rd: int = self.base_pointee_is_volatile(pool, trans, at.value) @@ -702,9 +702,9 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): opt_fp: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, field_ty, obj_ptr, field_info.Index) if opt_fp is None: return None return self._optional_field_result(pool, builder, trans, obj_ptr, opt_fp, field_ty, 0) - # t.VolatileT field: loads through the object carry the volatile qualifier + # volatile field: loads through the object carry the volatile qualifier field_vol_rd: int = self.Gen.StructGen.field_is_volatile(field_info) - # merge "the field's pointee is volatile": when the base is rawptr[t.VolatileT|T], + # merge "the field's pointee is volatile": when the base is rawptr[volatile|T], # field loads through it must also be volatile (OR of both flags) if vol_ba_rd != 0: field_vol_rd = 1 # union: bitcast obj_ptr to field_ty* then load @@ -913,7 +913,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field_by_class(parent_class, at.attr, trans.ModuleSha1, at, trans._from_imports) return self.Gen.StructGen.field_is_volatile(fe) - # pointee volatile (rawptr[t.VolatileT | T], i.e. C's volatile T*): resolves a base to a + # pointee volatile (rawptr[volatile | T], i.e. C's volatile T*): resolves a base to a # VarEntry/FieldEntry so that loads/stores through p[i] / p.field / *p carry the volatile qualifier. def _resolve_attr_field_entry(self, pool: memhub.MemBuddy*, trans: HT.Translator*, attr_node: ast.AST*) -> GenTypes.FieldEntry*: """Return the FieldEntry for an obj.field access via a non-fatal read-only resolution.""" diff --git a/App/lib/core/Gen/Expr/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index 0191f3e..8ca2d0b 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -577,7 +577,7 @@ novirtual class ExprGenBase: return self.Gen.AssignGen._stg_ty_equal(pool, a, b) # _agg_value_slot_ty - 值语义槽:源表达式的变量槽**自身**持有聚合物(`x: Foo`,Spec.PtrLevel == 0)。 # 真·指针值(`p: Foo*`,以及**裸类形参** `node: T` —— 其 ABI 即 T*,见 ClassGenVTable "objects are - # pointers")的 Spec.PtrLevel >= 1,返回 None,仍必须显式解引用(c.deref(p) / *p)。 + # pointers")的 Spec.PtrLevel >= 1,返回 None,仍必须显式解引用(*p / *p)。 # 返回该聚合类型;不适用时 None。 def _agg_value_slot_ty(self, node: ast.AST*, val: mlirlite.Value*, trans: HT.Translator*) -> mlirlite.LLVMType*: """Aggregate type when the source is a variable slot holding the aggregate by value; else None.""" @@ -779,9 +779,9 @@ novirtual class ExprGenBase: m_p2i: str = "implicit pointer-to-integer conversion is forbidden: an explicit cast (e.g. uint64(p) / int64(p) / int(p)) is required to assign a pointer to an integer type" # 带上两端类型与被赋值的变量名:否则只剩一句泛泛的禁令,无法判断是指针变量、 # 被改型的槽,还是上游把函数返回类型解析成了指针。 - p2i_txt: str = GenApi.escape_fstring_copy(f"; source type {self._type_text(builder.Pool, val.Ty)} -> target type {self._type_text(builder.Pool, target_ty)}") - # 不透明指针打印出来都是 !llvm.ptr,必须补 pointee 才能看出到底指向哪个结构体 - if self.get_ptr_level(val.Ty) > 0 and val.Ty.Pointee is not None: + p2i_txt: str = GenApi.escape_fstring_copy(f"; source type {self._type_text(builder.Pool, val.Ty)} -> target type {self._type_text(builder.Pool, target_ty)}") + # 不透明指针打印出来都是 !llvm.ptr,必须补 pointee 才能看出到底指向哪个结构体 + if self.get_ptr_level(val.Ty) > 0 and val.Ty.Pointee is not None: p2i_txt = f"{p2i_txt}; source pointee {self._type_text(builder.Pool, val.Ty.Pointee)}" p2i_var: str = "" vn_p2i: ast.AST* = self._value_node_of(node) @@ -820,16 +820,16 @@ novirtual class ExprGenBase: if iv < lo_c or iv > hi_c: self.Gen.TypeGenErr.fatal_error(node, f"narrowing truncation overflow: constant {iv} is outside the {target_bits}-bit representable range [{lo_c}, {hi_c}]; use an explicit cast or widen the target type", "OverflowError") return mlirlite.build_trunc(builder, val, target_ty) - # 规则 2026-10-13:目标 i1(bool / t.CBool)**不再**对宽整型做隐式真值归一化 + # 规则 2026-10-13:目标 i1(bool / bool)**不再**对宽整型做隐式真值归一化 # (旧的 `x != 0 -> 1/0`)。真值归一化会掩盖真实的位宽不匹配(如 `b: bool = some_i32`), - # 属静默转换,必须 fail-fast;需要显式 `bool(x)` / `t.CBool(x)`。 + # 属静默转换,必须 fail-fast;需要显式 `bool(x)` / `bool(x)`。 # 合法写法不受影响:比较(!=/==/…)、`and` / `or`、`not` 本身即产出 i1 # (translate_compare / translate_boolop / translate_unaryop),i1 源走上面的 # `val_bits == target_bits` 直接放行;True/False 常量走上面的常量豁免。 if target_bits == 1: - self.Gen.TypeGenErr.fatal_error(node, f"implicit narrowing is forbidden: a {val_bits}-bit value cannot be implicitly assigned to bool (i1) (it would be silently reduced to its truthiness); use an explicit cast (e.g. bool(x) / t.CBool(x))", "CastError") + self.Gen.TypeGenErr.fatal_error(node, f"implicit narrowing is forbidden: a {val_bits}-bit value cannot be implicitly assigned to bool (i1) (it would be silently reduced to its truthiness); use an explicit cast (e.g. bool(x))", "CastError") return val - self.Gen.TypeGenErr.fatal_error(node, f"implicit narrowing is forbidden: a {val_bits}-bit value cannot be implicitly assigned to a {target_bits}-bit type (the high bits would be lost); use an explicit cast (e.g. int32(x) / t.CInt32T(x)) or widen the target type", "CastError") + self.Gen.TypeGenErr.fatal_error(node, f"implicit narrowing is forbidden: a {val_bits}-bit value cannot be implicitly assigned to a {target_bits}-bit type (the high bits would be lost); use an explicit cast (e.g. int32(x)) or widen the target type", "CastError") return val # Float conversion. val_fbits: int = self.get_llvm_float_bits(val.Ty) @@ -869,7 +869,7 @@ novirtual class ExprGenBase: # 整个调用期间有效(生命周期覆盖调用),故合法用例不会悬垂。 # 唯有被调者**保存**此地址(如容器 append 挂链)才会悬垂 —— 这类写法必须由 # 源码显式声明为指针形参(`node: T*`)并传入既有对象的地址(此时实参本就是 - # 指针,不会走到此处隐式拷贝)。显式 T* / &v / c.addr(...) 的正常用法不受影响。 + # 指针,不会走到此处隐式拷贝)。显式 T* / &v / &v 的正常用法不受影响。 # 注意(2026-10-22):豁免 (b) 与"裸类形参 `f(a: T)` 的 ABI 是 T*"共用同一条 # 路径,coerce 这里只能看到 LLVM 的 `T*`,无法区分形参源码上写的是 `T` 还是 # `T*`。因此"值传给 T* 形参须显式 &a"这一条尚未在此处收紧,需在调用侧按 @@ -883,7 +883,7 @@ novirtual class ExprGenBase: if same_v2p == 0: ctor_v2p: mlirlite.LLVMType* = self._ctor_call_agg_ty(node, trans) if self._same_agg_ty(builder.Pool, ctor_v2p, val.Ty) == 0: - m_v2p: str = "implicit value/pointer conversion for non-basic types is forbidden (except construction materialization): a non-basic value cannot be implicitly converted to a pointer (Foo -> Foo*); to take its address use c.addr(...) / &v explicitly, or cast explicitly" + m_v2p: str = "implicit value/pointer conversion for non-basic types is forbidden (except construction materialization): a non-basic value cannot be implicitly converted to a pointer (Foo -> Foo*); to take its address use &v / &v explicitly, or cast explicitly" v2p_txt: str = GenApi.escape_fstring_copy(f"; source value type {self._type_text(builder.Pool, val.Ty)} -> target type {self._type_text(builder.Pool, target_ty)}") self.Gen.TypeGenErr.fatal_error(self._value_node_of(node), f"{m_v2p}{v2p_txt}", "CastError") return val @@ -903,7 +903,7 @@ novirtual class ExprGenBase: # `T*`(对象即指针),把它赋给同型值字段/变量时按值拷贝;`x: T` 这类值语义槽指针同理。 # 拷贝后目标独立、不会悬垂 —— 与「传参用指针」的 ABI 选择互不冲突。 # ② 构造物化(见 _ctor_call_agg_ty)。 - # 其余(不同型聚合 / 多级指针)仍 fail-fast,须显式 *p / c.deref(p) 或显式 cast。 + # 其余(不同型聚合 / 多级指针)仍 fail-fast,须显式 *p / *p 或显式 cast。 if self.is_ptr_type(val.Ty) != 0 and self.is_ptr_type(target_ty) == 0: target_kind: int = target_ty.kind() if target_kind == mlirlite.LLVMType.Struct or target_kind == mlirlite.LLVMType.Array: diff --git a/App/lib/core/Gen/Expr/ExprGenCdef.vp b/App/lib/core/Gen/Expr/ExprGenCdef.vp index 41737ab..20393dc 100644 --- a/App/lib/core/Gen/Expr/ExprGenCdef.vp +++ b/App/lib/core/Gen/Expr/ExprGenCdef.vp @@ -113,7 +113,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): i += 1 return 0 # _lookup_cross_module_cdefine - cross-module DefineT lookup: resolve the source module - # from from_imports, parse its pyi "NAME: t.DefineT = value", then cache in the current module. + # from from_imports, parse its pyi "NAME: DefineT = value", then cache in the current module. def _lookup_cross_module_cdefine(self, pool: memhub.MemBuddy*, name: str, from_imports: str, imported_modules: str = None, depth: int = 0, node: ast.AST* = None) -> int64: """Look up a DefineT constant across modules, returning its 64-bit value or -1""" # recursion-depth guard: re-export chains + imported_modules walk can loop and OOM; @@ -266,7 +266,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if pyi_buf[cs_j2] == '=': cs_eq2 = 1 break - if cs_j2 + 9 <= cs_le and string.strncmp(pyi_buf + cs_j2, "t.DefineT", 9) == 0: cs_marker = 1 + if cs_j2 + 9 <= cs_le and string.strncmp(pyi_buf + cs_j2, "DefineT", 9) == 0: cs_marker = 1 cs_j2 += 1 if cs_marker != 0 and cs_eq2 != 0: cd_sig = 1 @@ -299,8 +299,8 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): return -1 if bytes_read < PYI_READ_BUF_SIZE: pyi_buf[bytes_read] = 0 - # 8. search pyi_buf for the "name: t.DefineT = value" line - # format: NAME: t.DefineT = value + # 8. search pyi_buf for the "name: DefineT = value" line + # format: NAME: DefineT = value name_len: sizet = string.strlen(name) total_len: sizet = string.strlen(pyi_buf) pos: sizet = 0 @@ -370,21 +370,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): # skip spaces while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 - # check for type-ctor forms like t.CUnsignedLong(...) / t.CLong(...) / int(...); - # if so, skip the "t.CXxx(" prefix, parse inside the parens, ignore trailing ')'. - is_type_ctor: int = 0 - if eq_pos + 2 < line_start + line_len: - if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.': - # find the '(' position - paren_pos: sizet = eq_pos + 2 - while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(': paren_pos += 1 - if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(': - is_type_ctor = 1 - eq_pos = paren_pos + 1 # skip '(' - # skip possible leading spaces inside the parens - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': eq_pos += 1 - - # paren-wrapped flag: (1 << 23) / (512) / (A | B) + # paren-wrapped flag: (1 << 23) / (512) is_paren_expr: int = 0 if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '(': is_paren_expr = 1 diff --git a/App/lib/core/Gen/Expr/ExprGenConst.vp b/App/lib/core/Gen/Expr/ExprGenConst.vp index eb9be28..2457403 100644 --- a/App/lib/core/Gen/Expr/ExprGenConst.vp +++ b/App/lib/core/Gen/Expr/ExprGenConst.vp @@ -143,15 +143,15 @@ novirtual class ExprGenConst(ExprGenBase.ExprGenBase): bits: int = self.get_llvm_type_bits(ty) if bits != 0: if bits == 32: return "int" - if bits == 64: return "CSizeT" - if bits == 8: return "CInt8T" - if bits == 16: return "CInt16T" + if bits == 64: return "sizet" + if bits == 8: return "int8" + if bits == 16: return "int16" return None if self.is_ptr_type(ty) != 0: return "str" fbits: int = self.get_llvm_float_bits(ty) if fbits != 0: - if fbits == 64: return "CDouble" - if fbits == 32: return "CFloat" + if fbits == 64: return "double" + if fbits == 32: return "float" return None # _find_pool_var - find the pool variable in the context. # Tries "pool", "_mbuddy", "mbuddy", "mb" in order. diff --git a/App/lib/core/Gen/Expr/ExprGenName.vp b/App/lib/core/Gen/Expr/ExprGenName.vp index 0435a5a..17724ad 100644 --- a/App/lib/core/Gen/Expr/ExprGenName.vp +++ b/App/lib/core/Gen/Expr/ExprGenName.vp @@ -49,7 +49,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if self.Gen.TypeGenCDef.is_cdefine_found() != 0: if trans is None or self.Gen.VarGen.lookup_var(trans.SymTab, nm_id) is None: if self.Gen.TypeGenCDef.is_cdefine_str() != 0: - # String DefineT (e.g. ZLIB_VERSION: t.DefineT = "1.3.2"): return a global + # String DefineT (e.g. ZLIB_VERSION: DefineT = "1.3.2"): return a global # string (i8*) for `return ZLIB_VERSION`. cdef_sv: str = self.Gen.TypeGenCDef.lookup_cdefine_string(nm_id) if cdef_sv is not None: @@ -139,7 +139,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): return mod_alloca case _: pass - # t.VolatileT global: load carries volatile (prevents optimizing away repeated reads) + # volatile global: load carries volatile (prevents optimizing away repeated reads) vol_g: int = 0 if trans is not None: ve_g: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm_id) @@ -156,7 +156,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if trans._va_list_ptr is not None: return trans._va_list_ptr # Local variable lookup must precede the module-alias check, or a local with the same - # name as a module (e.g. local `c` after `import t, c`) would be misread and not found. + # name as a module would be misread and not found. alloca: mlirlite.Value* = self.Gen.VarGen.lookup_var(trans.SymTab, nm_id) if alloca is not None: load_ty: mlirlite.LLVMType* = None @@ -182,7 +182,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # Array variables decay to a pointer (base address) per C semantics; loading the # whole array value into "%s" reads wrong data (ClassArrayTest crash root cause). return alloca - # t.VolatileT local: load carries volatile + # volatile local: load carries volatile vol_l: int = 0 bo_l: int = 0 if trans is not None: @@ -289,10 +289,6 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # All lookup paths failed: fail-fast (NameError) instead of returning None and crashing # downstream. Exempt keywords/builtins (self/pool/None/_) whose absence is normal. if nm_id is None: return None - if string.strcmp(nm_id, "CIf") == 0 or string.strcmp(nm_id, "CIfdef") == 0 or string.strcmp(nm_id, "CIfndef") == 0 or string.strcmp(nm_id, "CElif") == 0 or string.strcmp(nm_id, "CElse") == 0 or string.strcmp(nm_id, "CEndif") == 0: - # The c.CIf-family spellings were removed; report the replacement. - self.Gen.TypeGenErr.fatal_error(node, "c.CIf/c.CIfdef/c.CIfndef/c.CElif/c.CElse/c.CEndif were removed; use the cif/celif/celse statements and the defined(NAME) predicate instead (e.g. `cif defined(NAME):` ... `celse:` ...)", "NameError") - return None if string.strcmp(nm_id, "self") == 0 or string.strcmp(nm_id, "pool") == 0 or string.strcmp(nm_id, "true") == 0 or string.strcmp(nm_id, "false") == 0 or string.strcmp(nm_id, "None") == 0 or string.strcmp(nm_id, "match") == 0 or string.strcmp(nm_id, "_") == 0: return None # Diagnostics: report the generic context, since "undefined name 'T'" is often far from the @@ -523,7 +519,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(sub.value) if nm.id is not None and trans is not None: - # rawptr[t.VolatileT | T] variable (volatile pointee): element loads (p[i] dereference) + # rawptr[volatile | T] variable (volatile pointee): element loads (p[i] dereference) # carry volatile; loading the pointer value itself does not. vol_sub_rd: int = self.Gen.VarGen.var_pointee_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm.id)) # nonlocal array/pointer: read the shared heap address from env (the outer alloca @@ -738,7 +734,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): # Check whether it is a pointer type if self.is_ptr_type(ptr_val.Ty) != 0: # Generic-path base (e.g. self.ptr / a complex expression): element loads carry volatile only - # when the base resolves to a VarEntry/FieldEntry marked rawptr[t.VolatileT|T]; otherwise 0. + # when the base resolves to a VarEntry/FieldEntry marked rawptr[volatile|T]; otherwise 0. vol_sub_gen: int = self.Gen.ExprGenAttr.base_pointee_is_volatile(pool, trans, sub.value) elem_ty2: mlirlite.LLVMType* = ptr_val.Ty.Pointee if elem_ty2 is not None: @@ -775,9 +771,8 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase): def _annot_is_64bit_scalar(self, annot: str) -> int: """Return 1 when the annotation is a 64-bit scalar | rawptr union (element type Int64).""" if annot is None: return 0 - if string.strstr(annot, "CInt64T") is not None: return 1 - if string.strstr(annot, "CUInt64T") is not None: return 1 - if string.strstr(annot, "CSizeT") is not None: return 1 + if string.strstr(annot, "int64") is not None: return 1 + if string.strstr(annot, "sizet") is not None: return 1 return 0 # subscript_base_store_kind - read-only base storage classification: 1 = array slot (whole-object diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index d8856b7..5222a33 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -274,7 +274,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if fe_fn_u.RetSign == GenTypes.FUNC_RET_SIGN_UNSIGNED: return 1 if fe_fn_u.Spec is not None and TSpec.SpecIsUnsigned(fe_fn_u.Spec.Ret) != 0: return 1 elif fk_u == ast.ASTKind.Attribute: - # Qualified type cast: t.CUInt16T(x); then method / module-qualified calls. + # Qualified type cast: uint16(x); then method / module-qualified calls. at_u: ast.Attribute* = ast.Attribute*(cl.func) if at_u.attr is not None and self._type_name_unsigned(at_u.attr) != 0: return 1 fe_at_u: GenTypes.FuncEntry* = self._attr_call_ret_entry(pool, at_u, trans) @@ -433,7 +433,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): fe_fn_s: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(nm_c.id) if fe_fn_s is not None and fe_fn_s.RetSign == GenTypes.FUNC_RET_SIGN_SIGNED: return 1 elif fk_s == ast.ASTKind.Attribute: - # Qualified signed cast (t.CInt16T(x)) or method / module-qualified call. + # Qualified signed cast (int16(x)) or method / module-qualified call. at_c: ast.Attribute* = ast.Attribute*(cl.func) if at_c.attr is not None: if self._spec_sign_from_annot(at_c.attr) == TSpec.TS_SIGN_SIGNED: return 1 diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index ecd0e6d..4948803 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -52,7 +52,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): # → 撞 coerce_to_type 的 CastError(现场:EscapeMethodTest 的 (C) 用例)。那是"嵌套 def # 只支持 int 返回"这个预先存在的缺口,此前被同文件更早的用例报错掩盖。 # 约定(最小改动的边界): - # · `fd.returns is None` 或注解是 `None` / `t.CVoid` → **保持 i32**(不改既有 ABI, + # · `fd.returns is None` 或注解是 `None` / `t.void` → **保持 i32**(不改既有 ABI, # 避免打断现有"无返回值/无注解"的嵌套 def;这是已知缺口,不在本次范围内); # · 其余注解采用 resolve_annotation_type 的结果;解析不出 → fail-fast,不静默兜底。 ret_ty_n: mlirlite.LLVMType* = i32_ty @@ -61,7 +61,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if fd.returns.kind() == ast.ASTKind.Constant: rc_n: ast.Constant* = ast.Constant*(fd.returns) if rc_n is not None and rc_n.const_kind == ast.CONST_NONE: keep_i32_n = 1 - if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, trans._imported_modules) != 0: keep_i32_n = 1 + if self.Gen.TypeGenResolve._is_void_marker(fd.returns) != 0: keep_i32_n = 1 if keep_i32_n == 0: rt_res_n: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, trans._imported_modules, trans._from_imports, trans, 0) if rt_res_n is None: @@ -79,7 +79,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): mlirlite.add_param(pool, func, i8_ptr_ty, "%env") # 2a. Nested function params join the promoted signature (i8* %env, args...); - # types go into the param_tys buffer (CVoid skipped, aligning with alloca indices). + # types go into the param_tys buffer (void skipped, aligning with alloca indices). imported_modules: str = trans._imported_modules from_imports: str = trans._from_imports param_tys: rawptr = pool.alloc(8 * 64) @@ -94,7 +94,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): arg_n: ast.Arg* = ast.Arg*(alist_n.get(ai_n)) if arg_n is None or arg_n.arg is None: continue if arg_n.annotation is not None: - if self.Gen.TypeGenResolve._is_builtin_marker(arg_n.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_bare_void(arg_n.annotation) != 0: continue pty_n: mlirlite.LLVMType* = i32_ty if arg_n.annotation is not None: resolved_n: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_n.annotation, imported_modules, from_imports, trans, 0) @@ -147,7 +147,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): arg_p: ast.Arg* = ast.Arg*(alist_p.get(api)) if arg_p is None or arg_p.arg is None: continue if arg_p.annotation is not None: - if self.Gen.TypeGenResolve._is_builtin_marker(arg_p.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_bare_void(arg_p.annotation) != 0: continue if idx_p >= param_count: break pty2_n: mlirlite.LLVMType* = i32_ty if param_tys is not None: @@ -165,12 +165,12 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): cls_nm_p: str = self.Gen.TypeGenResolve.extract_class_name_from_annotation(arg_p.annotation, imported_modules, pool, trans._from_imports) if cls_nm_p is not None: self.Gen.VarGen.set_var_annot_class_name(trans.SymTab, arg_p.arg, cls_nm_p) # const param: keep TPC's historical test (only whether the annotation contains - # t.ConstT, not the pointer depth); both sides align per type-descriptors.md. + # const, not the pointer depth); both sides align per type-descriptors.md. if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "ConstT", 0) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, arg_p.arg) - # t.VolatileT param: mark at declaration (same as the FuncGenDef main path) so + # volatile param: mark at declaration (same as the FuncGenDef main path) so # load/store of this param name in the body carry volatile. if self.Gen.TypeGenErr.has_decorator_marker(arg_p.annotation, "VolatileT", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, arg_p.arg) - # rawptr[t.VolatileT | T] param (volatile pointee): dereferences in the body carry + # rawptr[volatile | T] param (volatile pointee): dereferences in the body carry # volatile (same as the FuncGenDef main path). if self.Gen.TypeGenErr.has_pointee_volatile_marker(arg_p.annotation) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, arg_p.arg) pname2_n: str = pool.alloc(32) diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index b8a5c53..5587668 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -269,14 +269,14 @@ def has_decorator_marker(node: ast.AST*, marker_name: str, depth: int = 0) -> in # ---------------- has_pointee_volatile_marker (delegates to TypeGenErr.has_pointee_volatile_marker) ---------------- def has_pointee_volatile_marker(node: ast.AST*) -> int: - """Delegate to gen.has_pointee_volatile_marker (rawptr[t.VolatileT | T] field/var pointee)""" + """Delegate to gen.has_pointee_volatile_marker (rawptr[volatile | T] field/var pointee)""" if _g_gen is not None: return _g_gen.TypeGenErr.has_pointee_volatile_marker(node) return 0 # ---------------- is_const_object_marker (delegates to TypeGenErr.is_const_object_marker) ---------------- def is_const_object_marker(node: ast.AST*, var_ty: mlirlite.LLVMType*) -> int: - """Delegate to gen.is_const_object_marker (t.ConstT non-pointer object field/var)""" + """Delegate to gen.is_const_object_marker (const non-pointer object field/var)""" if _g_gen is not None: return _g_gen.TypeGenErr.is_const_object_marker(node, var_ty) return 0 diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 5c2d964..8abbb37 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -618,10 +618,6 @@ novirtual class ImportsGenMixin: def _check_import_sha1(self, node: ast.AST*, mod_name: str) -> int: """Fail-fast when an imported module's SHA1 is not registered.""" if mod_name is None: return 1 - # t / c were retired: their types are builtin and their C helpers now have language syntax. - if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0: - self._report_import_error(node, "`import t` / `import c` is retired; builtin types and C helpers no longer live in modules") - return 0 # ctraits (.vpi compile-time macro lib), viperbuild (compiler builtin macro lib) and # ffilib (compiler builtin FFI-declaration macro lib) stay exempt: they have no module # SHA1 because they emit no code at all (Pass 0 reads them, translation erases them). diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 14bb81b..33a1e0e 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -2573,7 +2573,7 @@ novirtual class StructGenMixin: if entry is not None and entry.Name is not None: if string.strcmp(entry.Name, name) == 0: return entry # Module-qualified name (module.Class): when the module resolves, match by module ownership exactly, to stop the bare-name fallback from grabbing a cross-module same-named class; if the module misses but the bare name is unique, fall back. - # Take the dot outside generic brackets (numpy.ndarray[t.CDouble] -> numpy + ndarray[t.CDouble]), else strrchr lands inside the subscript and truncates the module name (same root cause as lookup_field_by_class). + # Take the dot outside generic brackets (numpy.ndarray[double] -> numpy + ndarray[double]), else strrchr lands inside the subscript and truncates the module name (same root cause as lookup_field_by_class). dot_pos_q: str = self._last_dot_outside_brackets(name) if dot_pos_q is not None and dot_pos_q[1] != '\0': bare_f: str = dot_pos_q + 1 @@ -2780,7 +2780,7 @@ novirtual class StructGenMixin: # Supports module-qualified names: class_name may be "HT.Translator" while entry.Name is "Translator"; try exact match first, then fall back to the strrchr-extracted class name. if sha1 is not None: sha1_matched: int = 0 - # Compute the class-name fallback ("HT.Translator" -> "Translator"; "numpy.ndarray[t.CDouble]" -> "ndarray[t.CDouble]"). + # Compute the class-name fallback ("HT.Translator" -> "Translator"; "numpy.ndarray[double]" -> "ndarray[double]"). bare_name: str = class_name dot_pos_lfbc: str = self._last_dot_outside_brackets(class_name) if dot_pos_lfbc is not None: diff --git a/App/lib/core/Gen/Translator.vp b/App/lib/core/Gen/Translator.vp index 1a1bac9..449b958 100644 --- a/App/lib/core/Gen/Translator.vp +++ b/App/lib/core/Gen/Translator.vp @@ -30,7 +30,7 @@ define MAX_VARS = 1024 # Function-table capacity (single source of truth). Allocation happens in _init_state; # the registration-side max_count passed to add_func_to_table must be <= this capacity. define MAX_FUNCS = 1024 -# Reference convention: cross-module t.DefineT is readable only inside functions, so write +# Reference convention: cross-module DefineT is readable only inside functions, so write # qualified names there; the global/nonlocal name-table capacity must match on both guard sides. define MAX_GLOBAL_NAMES = 128 # Coroutine table capacity (VPC-M1): async function count / coroutine var and local-name count diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index e48041a..ad65aff 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -559,7 +559,7 @@ novirtual class TranslatorGenMixin: # t.StaticT vars (no cross-module use) are registered as (name, def module SHA1); # the logic stays inside _RegisterStaticModuleVar to avoid disturbing type inference. self._RegisterStaticModuleVar(trans, annot_node, var_name) - # Module-level t.Callable function pointers register (name -> return type) here so + # Module-level Callable function pointers register (name -> return type) here so # indirect calls resolve; done before any body translation, same as in-function AnnAssign. if annot_node is not None: ml_callable_ret: mlirlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot_node, trans._imported_modules,trans._from_imports, trans) @@ -984,15 +984,15 @@ novirtual class TranslatorGenMixin: # Register in the module scope if self.Gen.VarGen.define_module_var(trans.SymTab, var_name, gv_ref) == 0: - # t.VolatileT storage marker (union annotation): mark the global volatile so all + # volatile storage marker (union annotation): mark the global volatile so all # loads/stores carry LLVM volatile and busy-wait loops are not optimized away. if annot_node is not None: - # const object global: a non-pointer annotation with t.ConstT registers IsConst, + # const object global: a non-pointer annotation with const registers IsConst, # making later assignment/aug-assign/element-assign to the name fail-fast. if self.Gen.TypeGenErr.is_const_object_marker(annot_node, var_ty) != 0: self.Gen.VarGen.set_var_const(trans.SymTab, var_name) if self.Gen.TypeGenErr.has_decorator_marker(annot_node, "VolatileT", 0) != 0: self.Gen.VarGen.set_var_volatile(trans.SymTab, var_name) - # rawptr[t.VolatileT | T] (volatile pointee): loads/stores through p[i]/p.field/ - # c.Deref(p) carry volatile; distinct from the variable's own volatile qualifier. + # rawptr[volatile | T] (volatile pointee): loads/stores through p[i]/p.field/ + # *p carry volatile; distinct from the variable's own volatile qualifier. if self.Gen.TypeGenErr.has_pointee_volatile_marker(annot_node) != 0: self.Gen.VarGen.set_var_pointee_volatile(trans.SymTab, var_name) # Set AnnotClassName so attribute access can fall back to the class name when a union # type like Logger* is simplified to Ptr(i8). diff --git a/App/lib/core/Gen/Type/TypeGenBase.vp b/App/lib/core/Gen/Type/TypeGenBase.vp index 57986de..eb79eb7 100644 --- a/App/lib/core/Gen/Type/TypeGenBase.vp +++ b/App/lib/core/Gen/Type/TypeGenBase.vp @@ -48,7 +48,7 @@ novirtual class TypeGenBase: # 判定"是不是浮点常量"一律用 `!= 0`(既有调用处口径不变),只有浮点常量物化处区分 64/32: # `define PI: float = 3.14159...` 必须直接出 f32 常量,否则与 f32 字面量混算会多出 fpext。 CDefineDoubleFlags: list[int]* - CDefineStrFlags: list[int]* # 1=string value (e.g. ZLIB_VERSION: t.DefineT = "1.3.2") + CDefineStrFlags: list[int]* # 1=string value (e.g. ZLIB_VERSION: DefineT = "1.3.2") # 值表达式的**位宽**(bit);0=未知(按值推断)。来源:右侧显式强转(如 WORD(0x0080))优先, # 否则声明注解(define X: WORD = ... 的 T)。物化时据此定宽,避免小位宽常量被提升为 i32。 CDefineBits: list[int]* diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index cc4292b..9edc15b 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -32,8 +32,8 @@ def _ctypedef_idx_hash(name: str) -> uint64: # TypeGenCType - TypedefT table (register/lookup/constant evaluation); -# inheritance chain is one level; @t.NoVTable static binding. -@t.NoVTable +# inheritance chain is one level; @NoVTable static binding. +@NoVTable class TypeGenCType(TypeGenBase.TypeGenBase): """TypedefT table: register, lookup, scan declarations, eval const ints.""" @@ -381,7 +381,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase): line_len: sizet = i - line_start if line_len > 0 and td_buf is not None: # Parse both equivalent forms: the sugar "typedef N = V" and the - # annotation "N: t.TypedefT = V". + # annotation "N: TypedefT = V". if self.Gen.TypeGenResolve._parse_typedef_line(td_buf, src, line_start, line_len) != 0: name_buf: str = td_buf ty_buf: str = td_buf + string.strlen(td_buf) + 1 diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index c97eabd..25c9029 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -100,10 +100,10 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): """Report an error in Python style and exit (TypeError variant)""" return self.fatal_error(node, msg, "TypeError", col_start, col_end) def try_extract_callable_ret(self, pool: memhub.MemBuddy*, annot: ast.AST*, imported_modules: str, from_imports: str, trans: HT.Translator*) -> mlirlite.LLVMType*: - """Extract the return type of a function-pointer annotation (t.Callable[[A,B], R]); None for non-Callable or signature-less forms.""" + """Extract the return type of a function-pointer annotation (Callable[[A,B], R]); None for non-Callable or signature-less forms.""" if annot is None or annot.kind() != ast.ASTKind.Subscript: return None sub_cr: ast.Subscript* = ast.Subscript*(annot) - # The subscript test uses TypeGenResolve as the single source of truth (the t.Callable + # The subscript test uses TypeGenResolve as the single source of truth (the Callable # Attribute form is equivalent to the bare-name callable / Callable forms) if self.Gen.TypeGenResolve._IsCallableSubscriptValue(sub_cr.value) == 0: return None # slice must be Tuple(elts=[args_list, ret_node]); the one-element form @@ -151,7 +151,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): return 0 def has_pointee_volatile_marker(self, node: ast.AST*) -> int: - """Whether a rawptr[...] subscript argument carries the t.VolatileT marker (pointee-side volatile), 1=yes / 0=no.""" + """Whether a rawptr[...] subscript argument carries the volatile marker (pointee-side volatile), 1=yes / 0=no.""" if node is None or node.kind() != ast.ASTKind.Subscript: return 0 sub: ast.Subscript* = ast.Subscript*(node) if sub.value is None or sub.value.kind() != ast.ASTKind.Name: return 0 @@ -162,7 +162,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): return self.has_decorator_marker(sub.slice, "VolatileT", 0) def is_const_object_marker(self, node: ast.AST*, var_ty: mlirlite.LLVMType*) -> int: - """Whether a variable/field is itself a const object (1=yes / 0=no): annotation carries t.ConstT and the declared LLVM type is not a pointer.""" + """Whether a variable/field is itself a const object (1=yes / 0=no): annotation carries const and the declared LLVM type is not a pointer.""" if self.has_decorator_marker(node, "ConstT", 0) == 0: return 0 if var_ty is None: return 0 if var_ty.kind() == mlirlite.LLVMType.Ptr: return 0 diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index d41da2e..ef41d03 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -82,19 +82,6 @@ def SpecTypeNameBaseIs(name: str, base: str) -> int: def SpecSignFromTypeNameSpan(text: str, start: sizet, end: sizet) -> int: """Exact signedness of text[start:end]; TS_SIGN_UNKNOWN if not covered""" if text is None: return TS_SIGN_UNKNOWN - # --- t/c core unsigned primitives --- - if _spec_name_eq(text, start, end, "CUInt8T") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt16T") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt32T") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUInt64T") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedChar") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedShort") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedInt") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedLong") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUnsignedLongLong") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CSizeT") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CUIntPtrT") != 0: return TS_SIGN_UNSIGNED - if _spec_name_eq(text, start, end, "CBool") != 0: return TS_SIGN_UNSIGNED # --- builtin short names --- if _spec_name_eq(text, start, end, "sizet") != 0: return TS_SIGN_UNSIGNED if _spec_name_eq(text, start, end, "size_t") != 0: return TS_SIGN_UNSIGNED @@ -135,18 +122,6 @@ def SpecSignFromTypeNameSpan(text: str, start: sizet, end: sizet) -> int: if _spec_name_eq(text, start, end, "intptr") != 0: return TS_SIGN_SIGNED # --- builtin lowercase scalars --- if _spec_name_eq(text, start, end, "bool") != 0: return TS_SIGN_UNSIGNED - # --- t/c core signed primitives --- - if _spec_name_eq(text, start, end, "CInt8T") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt16T") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt32T") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt64T") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CSignedChar") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CShort") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CInt") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CLong") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CLongLong") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CPtrDiffT") != 0: return TS_SIGN_SIGNED - if _spec_name_eq(text, start, end, "CChar") != 0: return TS_SIGN_SIGNED if _spec_name_eq(text, start, end, "int") != 0: return TS_SIGN_SIGNED if _spec_name_eq(text, start, end, "char") != 0: return TS_SIGN_SIGNED return TS_SIGN_UNKNOWN @@ -450,40 +425,40 @@ def SpecToText(sp: TypeSpec*, buf: str, buf_size: sizet) -> int: return r -# _sig_hex_char - lower-case hex digit for 0..15 -def _sig_hex_char(n: int) -> char: - """Lower-case hex digit for a 0..15 nibble""" - if n < 10: return char('0' + n) - return char('a' + (n - 10)) - - -# SpecSigHash16 - 16-hex SHA1 of a canonical parameter-signature text. -# This is the overload symbol suffix: "{module sha1}.{name}_v{hash}". The text is built from -# SpecToText, which already expands aliases to iN/uN/fN, writes pointers as p:, arrays as -# arr[N]: and structs as st:{module sha1}.Name -- so `uint` and `int` never collide, and a -# cross-module class reference carries its owning module's sha1. -def SpecSigHash16(text: str) -> str: - """Return the 16-hex signature hash of a canonical text (PermPool string); None on failure""" - if text is None: return None - ctx: hashlib.sha1* = hashlib.sha1() - if ctx is None: return None - ctx.update(text) - digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN) - if digest is None: return None - ctx.final(digest) - out: str = CompilerFactory.factory.PermPool.alloc(17) - if out is None: - stdlib.free(digest) - return None - for i in range(8): - b: int = int(digest[i]) - out[i * 2] = _sig_hex_char((b >> 4) & 0xF) - out[i * 2 + 1] = _sig_hex_char(b & 0xF) - out[16] = '\0' - stdlib.free(digest) - return out - - +# _sig_hex_char - lower-case hex digit for 0..15 +def _sig_hex_char(n: int) -> char: + """Lower-case hex digit for a 0..15 nibble""" + if n < 10: return char('0' + n) + return char('a' + (n - 10)) + + +# SpecSigHash16 - 16-hex SHA1 of a canonical parameter-signature text. +# This is the overload symbol suffix: "{module sha1}.{name}_v{hash}". The text is built from +# SpecToText, which already expands aliases to iN/uN/fN, writes pointers as p:, arrays as +# arr[N]: and structs as st:{module sha1}.Name -- so `uint` and `int` never collide, and a +# cross-module class reference carries its owning module's sha1. +def SpecSigHash16(text: str) -> str: + """Return the 16-hex signature hash of a canonical text (PermPool string); None on failure""" + if text is None: return None + ctx: hashlib.sha1* = hashlib.sha1() + if ctx is None: return None + ctx.update(text) + digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN) + if digest is None: return None + ctx.final(digest) + out: str = CompilerFactory.factory.PermPool.alloc(17) + if out is None: + stdlib.free(digest) + return None + for i in range(8): + b: int = int(digest[i]) + out[i * 2] = _sig_hex_char((b >> 4) & 0xF) + out[i * 2 + 1] = _sig_hex_char(b & 0xF) + out[16] = '\0' + stdlib.free(digest) + return out + + def _spec_to_text(sp: TypeSpec*, buf: str, buf_size: sizet, depth: int, scratch: str) -> int: """Recursive implementation of SpecToText (depth limit SPEC_DEPTH_MAX)""" if sp is None or buf is None or buf_size == 0 or scratch is None or depth > SPEC_DEPTH_MAX: return 1 diff --git a/App/lib/core/Gen/VarGenMixin.vp b/App/lib/core/Gen/VarGenMixin.vp index 951ab6a..8444e86 100644 --- a/App/lib/core/Gen/VarGenMixin.vp +++ b/App/lib/core/Gen/VarGenMixin.vp @@ -173,7 +173,7 @@ novirtual class VarGenMixin: if sp.ElemBits == 64: return 1 return 0 - # set_var_volatile - mark a variable volatile (annotation union contains t.VolatileT). + # set_var_volatile - mark a variable volatile (annotation union contains volatile). # Every load/store of it carries LLVM volatile, preventing hoisting/removal of busy-wait loads. def set_var_volatile(self, symtab: GenTypes.SymbolTable*, name: str) -> int: """Mark a variable as volatile (VarEntry.IsVolatile=1), return 0=success / 1=failure""" @@ -189,8 +189,8 @@ novirtual class VarGenMixin: if entry is None: return 0 return entry.IsVolatile - # set_var_pointee_volatile - mark the pointed-to object volatile (rawptr[t.VolatileT | T]). - # Dereferences (p[i] / p.field / c.Deref(p)) then use LLVM volatile load/store on the pointee. + # set_var_pointee_volatile - mark the pointed-to object volatile (rawptr[volatile | T]). + # Dereferences (p[i] / p.field / *p) then use LLVM volatile load/store on the pointee. def set_var_pointee_volatile(self, symtab: GenTypes.SymbolTable*, name: str) -> int: """Mark the variable's pointee volatile (VarEntry.PointeeVolatile=1), return 0=success / 1=failure""" if symtab is None or name is None: return 1 @@ -205,7 +205,7 @@ novirtual class VarGenMixin: if entry is None: return 0 return entry.PointeeVolatile - # set_var_const - mark a variable as a const object (annotation has t.ConstT and the type is not a pointer). + # set_var_const - mark a variable as a const object (annotation has const and the type is not a pointer). # Assignment / augmented assignment / element assignment to it are then rejected (same rule as TPC). def set_var_const(self, symtab: GenTypes.SymbolTable*, name: str) -> int: """Mark a variable as a const object (VarEntry.IsConst=1), return 0=success / 1=failure""" @@ -222,7 +222,7 @@ novirtual class VarGenMixin: return entry.IsConst # set_var_byte_order - register a local variable's byte order (VarEntry.ByteOrder) from the - # `T | t.BigEndian` / `T | t.LittleEndian` annotation union: 1=BigEndian / 2=LittleEndian. + # `T | bigend` / `T | littlend` annotation union: 1=BigEndian / 2=LittleEndian. # The value is only 1/2 when a marker is present, so the local load/store paths bswap only then. def set_var_byte_order(self, symtab: GenTypes.SymbolTable*, name: str, byte_order: int) -> int: """Set a local variable's byte order (VarEntry.ByteOrder), return 0=success / 1=failure""" @@ -1522,7 +1522,7 @@ novirtual class VarGenMixin: return None return mlirlite.build_load(trans._cur_builder, slot_ty, slot) - # ---- repl_try_addr - session variable address-of (c.Addr(x) -> ctx slot address) ---- + # ---- repl_try_addr - session variable address-of (&x -> ctx slot address) ---- def repl_try_addr(self, trans: HT.Translator*, name: str, node: ast.AST*) -> mlirlite.Value*: """Session variable address-of: return the slot address (Ptr(value type)); None when unregistered, untyped, or outside the fragment body.""" if trans is None or trans.ReplCtx is None or name is None: return None @@ -1530,7 +1530,7 @@ novirtual class VarGenMixin: if entry is None: return None if self.repl_in_frag_scope(trans.SymTab) == 0: return None if entry.Kind == GenTypes.REPL_KIND_UNTYPED: - self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' has not been assigned yet (untyped), cannot take its address (c.Addr)", "NameError") + self.Gen.TypeGenErr.fatal_error(node, f"REPL: session variable '{name}' has not been assigned yet (untyped), cannot take its address (&x)", "NameError") return None pool: memhub.MemBuddy* = trans.Pool slot_ty: mlirlite.LLVMType* = self.repl_slot_ty(pool, entry) diff --git a/App/lib/core/Repl.vp b/App/lib/core/Repl.vp index 4721927..8040689 100644 --- a/App/lib/core/Repl.vp +++ b/App/lib/core/Repl.vp @@ -206,7 +206,7 @@ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int: # ============================================================ -# Session state: permanent buffers in PermPool; per-fragment strings in mb; t.Callable slots. +# Session state: permanent buffers in PermPool; per-fragment strings in mb; function-pointer slots. ReplFragFn: callable[[rawptr], int] = None # Fragment sequence number: module-level and monotonic, so names/files are never reused. ReplFragNo: int = 1 diff --git a/App/lib/lsp/LspSymbols.vp b/App/lib/lsp/LspSymbols.vp index f34ad34..2dda1b8 100644 --- a/App/lib/lsp/LspSymbols.vp +++ b/App/lib/lsp/LspSymbols.vp @@ -715,7 +715,7 @@ def _NameOnLine(pool: memhub.MemManager*, a: LspAnalysis*, line1: int, def _IsTypeAliasDecl(decl: ast.AST*) -> int: - """1 when decl is `name: t.TypedefT = type` (the canonical typedef form).""" + """1 when decl is `name: TypedefT = type` (the canonical typedef form).""" if decl is None or decl.kind() != ast.ASTKind.AnnAssign: return 0 ann: ast.AST* = ((ast.AnnAssign*)(decl)).annotation @@ -724,9 +724,6 @@ def _IsTypeAliasDecl(decl: ast.AST*) -> int: if ann.kind() == ast.ASTKind.Name: nm: ast.Name* = (ast.Name*)(ann) return 1 if nm.id is not None and string.strcmp(nm.id, "TypedefT") == 0 else 0 - if ann.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = (ast.Attribute*)(ann) - return 1 if at.attr is not None and string.strcmp(at.attr, "CTypedef") == 0 else 0 return 0