diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 79ea7ca..ef6c800 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -440,8 +440,6 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, depth: int, prefix: nm[tl] = 0 is_last: int = 0 if idx + 1 >= token_count: is_last = 1 - builtin: int = 0 - if string.strcmp(nm, "t") == 0 or string.strcmp(nm, "c") == 0: builtin = 1 dep_sha1: str = _PhaseAResolveDepSha1(nm) txt_ok: int = 0 if dep_sha1 is not None: txt_ok = _PhaseATextLLExists(temp_dir, td_len, dep_sha1) @@ -449,10 +447,7 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, depth: int, prefix: # stack pointer for a literal -> printf %s crashes and the graph output is swallowed) br_1: str = "|-- " br_2: str = "`-- " - if builtin != 0: - if is_last != 0: stdio.printf("%s%s%s (builtin)\n", prefix, br_2, nm) - else: stdio.printf("%s%s%s (builtin)\n", prefix, br_1, nm) - elif dep_sha1 is None: + if dep_sha1 is None: if is_last != 0: stdio.printf("%s%s%s (unresolved)\n", prefix, br_2, nm) else: stdio.printf("%s%s%s (unresolved)\n", prefix, br_1, nm) elif txt_ok != 0: @@ -463,7 +458,7 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, depth: int, prefix: else: stdio.printf("%s%s%s [MISS] text.ll=%s\n", prefix, br_1, nm, dep_sha1) # Drill down: MISS follows the whole chain (to PA_GRAPH_DEPTH_MAX); OK probes 1 level only can_expand: int = 0 - if dep_sha1 is not None and builtin == 0: + if dep_sha1 is not None: if txt_ok == 0: if depth + 1 < PA_GRAPH_DEPTH_MAX: can_expand = 1 else: diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 41992ad..3eabcc6 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -776,27 +776,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf tree_children: list[ast.AST*]* = tree.children n: sizet = len(tree_children) - # Pass 1: detect import t/c - has_import_t: int = 0 - has_import_c: int = 0 - for i in range(int(n)): - stmt: ast.AST* = tree_children.get(i) - if stmt is not None and stmt.kind() == ast.ASTKind.Import: - imp: ast.Import* = ast.Import*(stmt) - if imp.names is not None: - imp_names: list[ast.AST*]* = imp.names - an: sizet = len(imp_names) - for ai in range(int(an)): - al: ast.Alias* = ast.Alias*(imp_names.get(ai)) - if al is not None and al.name is not None: - if string.strcmp(al.name, "t") == 0: has_import_t = 1 - elif string.strcmp(al.name, "c") == 0: has_import_c = 1 - - # Add missing import t/c - if has_import_t == 0 and has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import t, c\n\n") - elif has_import_t == 0: pos = _PyiEmit(buf, buf_size, pos, "import t\n\n") - elif has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import c\n\n") - else: pos = _PyiEmit(buf, buf_size, pos, "\n") + # t / c are retired compiler-internal modules: the stub never injects their imports. + pos = _PyiEmit(buf, buf_size, pos, "\n") # Pass 2: emit declarations for i in range(int(n)): @@ -886,12 +867,9 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf # If there is a value (e.g. a CDefine constant) emit = value. # CTypedef is special: its value is a type expression, rendered by _PyiTypeStr. is_ctypedef_ann: int = 0 - if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Attribute: - ctd_at: ast.Attribute* = ast.Attribute*(aa.annotation) - if ctd_at.attr is not None and string.strcmp(ctd_at.attr, "CTypedef") == 0: - if ctd_at.value is not None and ctd_at.value.kind() == ast.ASTKind.Name: - ctd_mod: ast.Name* = ast.Name*(ctd_at.value) - if ctd_mod.id is not None and string.strcmp(ctd_mod.id, "t") == 0: is_ctypedef_ann = 1 + if aa.annotation is not None and aa.annotation.kind() == ast.ASTKind.Name: + ctd_nm: ast.Name* = ast.Name*(aa.annotation) + if ctd_nm.id is not None and string.strcmp(ctd_nm.id, "CTypedef") == 0: is_ctypedef_ann = 1 if is_ctypedef_ann != 0 and aa.value is not None: pos = _PyiEmit(buf, buf_size, pos, " = ") pos = _PyiTypeStr(buf, buf_size, pos, aa.value) diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index c071330..40b4bae 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -1645,10 +1645,10 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.L stdlib.free(inner_buf_rp) if inner_ty_rp is not None: return mlirlite.Ptr(pool, inner_ty_rp) return None - # t.CPtr[T] / c.CPtr[T] subscript pointers (nesting allowed, e.g. t.CPtr[t.CPtr] - # -> Ptr(Ptr(i8))); same as TypeGenResolve's Subscript(CPtr) branch: Ptr(resolve(T)). + # CPtr[T] subscript pointers (nesting allowed, e.g. CPtr[CPtr] -> Ptr(Ptr(i8))); + # same as TypeGenResolve's Subscript(CPtr) branch: Ptr(resolve(T)). cptr_sub_pfx: sizet = 0 - if string.strncmp(seg, "t.CPtr[", 7) == 0 or string.strncmp(seg, "c.CPtr[", 7) == 0: cptr_sub_pfx = 7 + if string.strncmp(seg, "CPtr[", 6) == 0: cptr_sub_pfx = 6 if cptr_sub_pfx > 0: seg_len_cp: sizet = string.strlen(seg) if seg_len_cp > cptr_sub_pfx + 1 and seg[seg_len_cp - 1] == ']': @@ -1661,15 +1661,12 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.L stdlib.free(inner_buf_cp) if inner_ty_cp is not None: return mlirlite.Ptr(pool, inner_ty_cp) return None - # t.XXX / c.XXX built-in type mapping - if string.strncmp(seg, "t.", 2) == 0 or string.strncmp(seg, "c.", 2) == 0: - attr_nm: str = seg + 2 - # t.CExport is an export marker, not a real type; FuncGenDef maps it to Void, + # Bare builtin type names (int8 / uint64 / sizet / CPtr / CExport ...) + if string.strchr(seg, '.') is None: + # CExport is an export marker, not a real type; FuncGenDef maps it to Void, # so normalize it here too or cross-module return types fail fast. - if string.strcmp(attr_nm, "CExport") == 0: return mlirlite.Void(pool) - # [stage 2] unified: CTypedef dynamic table first (library typedefs analyzed normally), - # on miss fall back to map_t_type (t/c library internal special-casing). - mapped_ty: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, attr_nm, None, None) + if string.strcmp(seg, "CExport") == 0: return mlirlite.Void(pool) + mapped_ty: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, seg, None, None) if mapped_ty is not None: return mapped_ty return None # module-qualified class name "memhub.MemBuddy" -> use last segment to look up struct @@ -1689,7 +1686,7 @@ def _resolve_single_vpi_type_str(pool: memhub.MemBuddy*, seg: str) -> mlirlite.L # bare enum name -> EnumTable fallback (as above: enums are not in StructTable) bare_enum_ty: mlirlite.LLVMType* = GenApi.get_enum_base_type(seg) if bare_enum_ty is not None: return bare_enum_ty - # bare typedef name (e.g. VOIDPTR): CTypedef dynamic table first, on miss fall back to map_t_type + # bare typedef name (e.g. VOIDPTR): CTypedef dynamic table first, on miss fall back to map_builtin_type mapped_bare: mlirlite.LLVMType* = GenApi.resolve_typedef_or_map(pool, seg, None, None) if mapped_bare is not None: return mapped_bare return None @@ -1793,7 +1790,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m seg_buf[seg_len2] = '\0' # CPtr subscript segments must be recognized first: the definition side treats # `X*[T]` as "CPtr side contributes N pointer levels, the other side the base". - if string.strncmp(seg_buf, "t.CPtr[", 7) == 0 or string.strncmp(seg_buf, "c.CPtr[", 7) == 0: + if string.strncmp(seg_buf, "CPtr[", 6) == 0: seg_ty_cs: mlirlite.LLVMType* = _resolve_single_vpi_type_str(pool, seg_buf) if seg_ty_cs is not None: # Count outer Ptr nesting (same as the definition side). Do not update the @@ -1813,10 +1810,10 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m if lvl_cs > cptr_sub_lvl: cptr_sub_lvl = lvl_cs cptr_sub_ty = seg_ty_cs - elif string.strcmp(seg_buf, "t.CPtr") == 0 or string.strcmp(seg_buf, "CPtr") == 0: has_cptr = 1 - elif string.strcmp(seg_buf, "t.CRef") == 0 or string.strcmp(seg_buf, "CRef") == 0: has_cref = 1 - elif string.strcmp(seg_buf, "t.CTempRef") == 0 or string.strcmp(seg_buf, "CTempRef") == 0: has_cref = 1 - elif string.strcmp(seg_buf, "void") == 0 or string.strcmp(seg_buf, "CVoid") == 0 or string.strcmp(seg_buf, "void") == 0: + elif string.strcmp(seg_buf, "CPtr") == 0: has_cptr = 1 + elif string.strcmp(seg_buf, "CRef") == 0: has_cref = 1 + elif string.strcmp(seg_buf, "CTempRef") == 0: has_cref = 1 + elif string.strcmp(seg_buf, "void") == 0 or string.strcmp(seg_buf, "CVoid") == 0: # Bare void is an alias of t.CVoid and must be handled the same, else the # else branch sets first_td and produces the illegal Ptr(Void) (void* = i8*). has_cvoid = 1 @@ -2614,9 +2611,9 @@ def _vpi_class_has_packed(decorator_list: list[ast.AST*]*) -> int: if deco is None: continue if deco.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue - at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + if cl.func is None or cl.func.kind() != ast.ASTKind.Name: continue + at0: ast.Name* = ast.Name*(cl.func) + if at0.id is None or string.strcmp(at0.id, "Attribute") != 0: continue if cl.args is None: continue an: sizet = len(cl.args) for ai in range(int(an)): @@ -3527,12 +3524,7 @@ def _repl_stub_deco_flags(deco_list: list[ast.AST*]*) -> int: if deco is None: continue nm: str = None k: int = deco.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(deco) - if at.attr is not None and at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: nm = at.attr - elif k == ast.ASTKind.Name: + if k == ast.ASTKind.Name: nn: ast.Name* = ast.Name*(deco) nm = nn.id if nm is None: continue diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index e8ad06a..6eff43f 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -23,14 +23,14 @@ novirtual class AssignGenMixin: RecoverFound: int - # Check whether an annotation is t.CDefine (module-level function) + # Check whether an annotation is the CDefine marker (module-level function) def is_cdefine_annotation(self, annot: ast.AST*) -> int: - """Return 1 if the annotation is t.CDefine, else 0.""" + """Return 1 if the annotation is the CDefine marker, else 0.""" if annot is None: return 0 k: int = annot.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(annot) - if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: return 1 + if k == ast.ASTKind.Name: + nm: ast.Name* = ast.Name*(annot) + if nm.id is not None and string.strcmp(nm.id, "CDefine") == 0: return 1 return 0 if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(annot) @@ -325,13 +325,9 @@ novirtual class AssignGenMixin: self.Gen.TypeGenErr.fatal_error(node, f"[VPC] shift count out of range: the count {v} is >= the left operand width {lhs_bits} bits; " f"the result would be 0 or undefined (not a value the compiler may guess). " f"Fix: use a count < {lhs_bits}, or widen the left operand.", "ValueError") def _is_cdefine_marker_node(self, node: ast.AST*) -> int: - """Return 1 if the node is a t.CDefine marker node.""" + """Return 1 if the node is the CDefine marker node.""" if node is None: return 0 k: int = node.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(node) - if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: return 1 - return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None and string.strcmp(nm.id, "CDefine") == 0: return 1 @@ -363,7 +359,7 @@ novirtual class AssignGenMixin: def _int_bits_of_type_name(self, pool: memhub.MemBuddy*, nm: str, depth: int) -> int: """类型名 → 整数位宽(0=未知/非整数)。depth 防 typedef 环。 - 覆盖:内建名(int/bool/int8../uint64/sizet)、`t.CXxx`(map_t_type)、 + 覆盖:内建名(int/bool/int8../uint64/sizet)、`t.CXxx`(map_builtin_type)、 以及**用户 typedef**(如 stdint 的 `WORD: t.CTypedef = uint16` —— 经 lookup_ctypedef 取其底层类型文本再递归定宽)。此前用户 typedef 一律返回 0,导致 `define X: WORD = ...` 的声明宽度不参与校验/物化。 @@ -380,7 +376,7 @@ novirtual class AssignGenMixin: if string.strcmp(nm, "int32") == 0 or string.strcmp(nm, "uint32") == 0: return 32 if string.strcmp(nm, "int64") == 0 or string.strcmp(nm, "uint64") == 0: return 64 if string.strcmp(nm, "sizet") == 0 or string.strcmp(nm, "size_t") == 0: return 64 - ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, nm) + ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_builtin_type(pool, nm) if ty is not None: match ty: case mlirlite.LLVMType.Int(bits): @@ -432,7 +428,7 @@ novirtual class AssignGenMixin: def _float_kind_of_type_name(self, pool: memhub.MemBuddy*, nm: str, depth: int) -> int: """类型名 → 1 表示它是 32 位 float(f32),0 表示 double 或非浮点/未知。depth 防 typedef 环。 - 覆盖:内建名 float、`t.CFloat` / `t.CFloat32T`(map_t_type)、用户/include typedef(递归展开)。 + 覆盖:内建名 float、`t.CFloat` / `t.CFloat32T`(map_builtin_type)、用户/include typedef(递归展开)。 """ if nm is None or depth > 10: return 0 # 去掉模块/类限定前缀:`t.CFloat` → `CFloat`;`stdint.float32` → `float32` @@ -441,7 +437,7 @@ novirtual class AssignGenMixin: return self._float_kind_of_type_name(pool, dot + 1, depth + 1) if string.strcmp(nm, "float") == 0: return 1 if string.strcmp(nm, "float32") == 0: return 1 - ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, nm) + ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_builtin_type(pool, nm) if ty is not None: match ty: case mlirlite.LLVMType.Float(bits): @@ -1502,34 +1498,22 @@ novirtual class AssignGenMixin: return 0 def _is_addrlike_call(self, node: ast.AST*) -> int: - """Return 1 if the rhs is an explicit pointer expression (c.Addr/c.Deref/c.Cast/c.Ptr call, or new-syntax `&x` / `*p`).""" + """Return 1 if the rhs is an explicit pointer expression (`&x` / `*p`). + """ if node is None: return 0 - # New syntax (R3/R4): `&x` and `*p` parse as UnaryOp(AddrOf) / UnaryOp(Deref) and replace the - # c.Addr / c.Deref call forms. A pointer-valued RHS must not take the module-global - # "object with static storage -> copy the object" branch, so both forms count as addrlike. + # `&x` and `*p` parse as UnaryOp(AddrOf) / UnaryOp(Deref). A pointer-valued RHS must not + # take the module-global "object with static storage -> copy the object" branch. if node.kind() == ast.ASTKind.UnaryOp: uo_al: ast.UnaryOp* = ast.UnaryOp*(node) if uo_al.op == ast.OpKind.AddrOf: return 1 if uo_al.op == ast.OpKind.Deref: return 1 return 0 - if node.kind() != ast.ASTKind.Call: return 0 - cl: ast.Call* = ast.Call*(node) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: return 0 - at: ast.Attribute* = ast.Attribute*(cl.func) - if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 - vn: ast.Name* = ast.Name*(at.value) - if vn.id is None or string.strcmp(vn.id, "c") != 0: return 0 - if at.attr is None: return 0 - if string.strcmp(at.attr, "Addr") == 0: return 1 - if string.strcmp(at.attr, "Deref") == 0: return 1 - if string.strcmp(at.attr, "Cast") == 0: return 1 - if string.strcmp(at.attr, "Ptr") == 0: return 1 return 0 def _is_addr_of_expr(self, node: ast.AST*) -> int: - """Return 1 only for an explicit address-of expression (`&x` / `c.Addr(x)`). + """Return 1 only for an explicit address-of expression (`&x`). - Distinct from _is_addrlike_call, which also counts deref/cast forms: assigning a *deref* + Distinct from _is_addrlike_call, which also counts deref forms: assigning a *deref* result (`*p`) to a value-typed variable is a legitimate value copy, so only `&x` indicates a missing `*` in the annotation. """ @@ -1538,14 +1522,6 @@ novirtual class AssignGenMixin: uo_ao: ast.UnaryOp* = ast.UnaryOp*(node) if uo_ao.op == ast.OpKind.AddrOf: return 1 return 0 - if node.kind() != ast.ASTKind.Call: return 0 - cl_ao: ast.Call* = ast.Call*(node) - if cl_ao.func is None or cl_ao.func.kind() != ast.ASTKind.Attribute: return 0 - at_ao: ast.Attribute* = ast.Attribute*(cl_ao.func) - if at_ao.value is None or at_ao.value.kind() != ast.ASTKind.Name: return 0 - vn_ao: ast.Name* = ast.Name*(at_ao.value) - if vn_ao.id is None or string.strcmp(vn_ao.id, "c") != 0: return 0 - if at_ao.attr is not None and string.strcmp(at_ao.attr, "Addr") == 0: return 1 return 0 def _DerefPunBits(self, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*) -> int: @@ -1577,20 +1553,65 @@ novirtual class AssignGenMixin: if string.strcmp(ty_nm, "CUInt64T") == 0: return 1 if string.strcmp(ty_nm, "CInt64T") == 0: return 1 if string.strcmp(ty_nm, "CSizeT") == 0: return 1 + # builtin 64-bit short names + if string.strcmp(ty_nm, "sizet") == 0: return 1 + if string.strcmp(ty_nm, "size_t") == 0: return 1 + if string.strcmp(ty_nm, "int64") == 0: return 1 + if string.strcmp(ty_nm, "uint64") == 0: return 1 + if string.strcmp(ty_nm, "intfast64") == 0: return 1 + if string.strcmp(ty_nm, "uintfast64") == 0: return 1 + if string.strcmp(ty_nm, "intleast64") == 0: return 1 + if string.strcmp(ty_nm, "uintleast64") == 0: return 1 + if string.strcmp(ty_nm, "longlong") == 0: return 1 + if string.strcmp(ty_nm, "ulonglong") == 0: return 1 + if string.strcmp(ty_nm, "ptrdifft") == 0: return 1 return 0 def _is_scalar_ty_name(self, ty_name: str) -> int: """Return 1 if the type name is a known pure scalar (whitelist).""" if ty_name is None: return 0 - # Strip the t./c. namespace prefix so int and bare aliases are judged the same - if ty_name[0] == 't' and ty_name[1] == '.': ty_name += 2 - elif ty_name[0] == 'c' and ty_name[1] == '.': ty_name += 2 if string.strchr(ty_name, '|') is not None: return 0 if string.strchr(ty_name, '*') is not None: return 0 if string.strcmp(ty_name, "str") == 0: return 0 if string.strcmp(ty_name, "bytes") == 0: return 0 if string.strcmp(ty_name, "CPtr") == 0: return 0 if string.strstr(ty_name, "Ptr") is not None: return 0 + # builtin short type names + if string.strcmp(ty_name, "sizet") == 0: return 1 + if string.strcmp(ty_name, "size_t") == 0: return 1 + if string.strcmp(ty_name, "int8") == 0: return 1 + if string.strcmp(ty_name, "int16") == 0: return 1 + if string.strcmp(ty_name, "int32") == 0: return 1 + if string.strcmp(ty_name, "int64") == 0: return 1 + if string.strcmp(ty_name, "uint8") == 0: return 1 + if string.strcmp(ty_name, "uint16") == 0: return 1 + if string.strcmp(ty_name, "uint32") == 0: return 1 + if string.strcmp(ty_name, "uint64") == 0: return 1 + if string.strcmp(ty_name, "intfast8") == 0: return 1 + if string.strcmp(ty_name, "intfast16") == 0: return 1 + if string.strcmp(ty_name, "intfast32") == 0: return 1 + if string.strcmp(ty_name, "intfast64") == 0: return 1 + if string.strcmp(ty_name, "uintfast8") == 0: return 1 + if string.strcmp(ty_name, "uintfast16") == 0: return 1 + if string.strcmp(ty_name, "uintfast32") == 0: return 1 + if string.strcmp(ty_name, "uintfast64") == 0: return 1 + if string.strcmp(ty_name, "intleast8") == 0: return 1 + if string.strcmp(ty_name, "intleast16") == 0: return 1 + if string.strcmp(ty_name, "intleast32") == 0: return 1 + if string.strcmp(ty_name, "intleast64") == 0: return 1 + if string.strcmp(ty_name, "uintleast8") == 0: return 1 + if string.strcmp(ty_name, "uintleast16") == 0: return 1 + if string.strcmp(ty_name, "uintleast32") == 0: return 1 + if string.strcmp(ty_name, "uintleast64") == 0: return 1 + if string.strcmp(ty_name, "uchar") == 0: return 1 + if string.strcmp(ty_name, "short") == 0: return 1 + if string.strcmp(ty_name, "ushort") == 0: return 1 + if string.strcmp(ty_name, "uint") == 0: return 1 + if string.strcmp(ty_name, "long") == 0: return 1 + if string.strcmp(ty_name, "ulong") == 0: return 1 + if string.strcmp(ty_name, "longlong") == 0: return 1 + if string.strcmp(ty_name, "ulonglong") == 0: return 1 + if string.strcmp(ty_name, "ptrdifft") == 0: return 1 # Whitelist: known pure scalars (base names + stdint uppercase aliases) if string.strcmp(ty_name, "int") == 0: return 1 if string.strcmp(ty_name, "char") == 0: return 1 @@ -1913,7 +1934,7 @@ novirtual class AssignGenMixin: def const_assign_msg(self, kind: str, name: str, src_name: str) -> str: """Build the const-assignment error message used by const_assign_fail.""" decl: str = "(annotation contains t.CConst; the source name at the declaration was not recorded)" - if src_name is not None: decl = f"t.CConst | {src_name}" + if src_name is not None: decl = f"CConst | {src_name}" return GenApi.escape_fstring_copy(f"cannot assign to const variable '{name}' ({kind}); " f"declaration type (including const): {decl}" f"; fix: remove the const descriptor / t.CConst from the declaration, or assign once at the declaration " f"and afterwards use only non-const copies/temporaries; a const object forbids assignment, " f"augmented assignment and element assignment within its scope, and this never degrades to a warning") def const_assign_fail(self, node: ast.AST*, kind: str, name: str, src_name: str) -> int: @@ -2242,18 +2263,12 @@ novirtual class AssignGenMixin: if annot is None or annot.kind() != ast.ASTKind.Subscript: return 0 sub: ast.Subscript* = ast.Subscript*(annot) if sub.value is None or sub.slice is None: return 0 - if sub.value.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(sub.value) - if at.attr is None or string.strcmp(at.attr, "CArray") != 0: return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 - mv: ast.Name* = ast.Name*(at.value) - if mv.id is None or string.strcmp(mv.id, "t") != 0: return 0 - elif sub.value.kind() == ast.ASTKind.Name: - # Bare CArray / builtin rawarray / builtin array are all equivalent to t.CArray + if sub.value.kind() == ast.ASTKind.Name: + # Bare CArray / builtin rawarray / builtin array are all equivalent. bn: ast.Name* = ast.Name*(sub.value) if bn.id is None or (string.strcmp(bn.id, "CArray") != 0 and string.strcmp(bn.id, "rawarray") != 0 and string.strcmp(bn.id, "array") != 0): return 0 else: return 0 - # Single-param form: slice is not a Tuple (e.g. t.CArray[u64]) + # Single-param form: slice is not a Tuple (e.g. CArray[u64]) if sub.slice.kind() != ast.ASTKind.Tuple: return 1 # Two-param form with count=None is equivalent to single-param tup: ast.Tuple* = ast.Tuple*(sub.slice) diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 56fc13a..f25e6dc 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -669,21 +669,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): return buf return "" - # Attribute: t.ASM_DESCR.XXX or t.XXX + # Attribute: ASM_DESCR.XXX if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) - # t.ASM_DESCR.XXX - if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: - inner: ast.Attribute* = ast.Attribute*(at.value) - if inner.value is not None and inner.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name* = ast.Name*(inner.value) - if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0: - if inner.attr is not None and string.strcmp(inner.attr, "ASM_DESCR") == 0: return self._resolve_register(at.attr) - # t.XXX shorthand form if at.value is not None and at.value.kind() == ast.ASTKind.Name: mod_nm2: ast.Name* = ast.Name*(at.value) - if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0: return self._resolve_register(at.attr) - # Bare ASM_DESCR.XXX: equivalent form without the t. prefix if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "ASM_DESCR") == 0: return self._resolve_register(at.attr) return "" @@ -724,12 +714,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase): if string.strcmp(nm.id, "irinp") == 0: return "LInp" if string.strcmp(nm.id, "irout") == 0: return "LOut" return None - if node.func.kind() != ast.ASTKind.Attribute: return None - at: ast.Attribute* = ast.Attribute*(node.func) - if at.value is None or at.value.kind() != ast.ASTKind.Name: return None - mod_nm: ast.Name* = ast.Name*(at.value) - if mod_nm.id is None or string.strcmp(mod_nm.id, "c") != 0: return None - return at.attr + return None def _asm_name_is_mangled(self, name: str) -> int: diff --git a/App/lib/core/Gen/Call/CallGenDispatch.vp b/App/lib/core/Gen/Call/CallGenDispatch.vp index b4faf3b..844738a 100644 --- a/App/lib/core/Gen/Call/CallGenDispatch.vp +++ b/App/lib/core/Gen/Call/CallGenDispatch.vp @@ -248,54 +248,28 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): # irinp/irout standalone calls return 0 (meaningful only inside __llvmir__ f-strings) return mlirlite.ConstInt(pool, mlirlite.Int32(pool), 0, "0") - # Detect c.Deref / c.DerefAs / c.Addr special calls (inline IR, no call emitted) - # and coro.* coroutine interception (inline translation, VPC-M1). + # Detect coro.* coroutine interception (inline translation, VPC-M1). if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: at_node: ast.Attribute* = ast.Attribute*(cl.func) if at_node.value is not None and at_node.value.kind() == ast.ASTKind.Name: mod_nm: ast.Name* = ast.Name*(at_node.value) is_coro_mod: int = 0 if mod_nm.id is not None and string.strcmp(mod_nm.id, "coro") == 0: is_coro_mod = 1 - if mod_nm.id is not None and (string.strcmp(mod_nm.id, "c") == 0 or is_coro_mod != 0): - if string.strcmp(func_name, "Deref") == 0: return self.Gen.CallGenCBuiltin.translate_c_deref(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "DerefAs") == 0: return self.Gen.CallGenCBuiltin.translate_c_derefas(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Addr") == 0: return self.Gen.CallGenCBuiltin.translate_c_addr(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Set") == 0: - # c.Set(a, b) = a = b (assignment, not pointer deref). Treating it as a plain - # call would emit @Set and fail to link (undefined reference to `Set'). - return self.Gen.CallGenCBuiltin.translate_c_set(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Load") == 0: return self.Gen.CallGenCBuiltin.translate_c_load(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Asm") == 0: - # translate_c_asm returns None for void: set the hit flag so translate_call - # does not fall through to the external function path. - if hit_box is not None: hit_box[0] = 1 - return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "LLVMIR") == 0: - # c.LLVMIR always returns void (None): set the hit flag - if hit_box is not None: hit_box[0] = 1 - return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "LInp") == 0 or string.strcmp(func_name, "LOut") == 0: - # c.LInp/c.LOut standalone calls return 0 (only meaningful in c.LLVMIR f-strings) - return mlirlite.ConstInt(pool, mlirlite.Int32(pool), 0, "0") - elif string.strcmp(func_name, "CIf") == 0 or string.strcmp(func_name, "CIfdef") == 0 or string.strcmp(func_name, "CIfndef") == 0 or string.strcmp(func_name, "CElif") == 0 or string.strcmp(func_name, "CElse") == 0 or string.strcmp(func_name, "CEndif") == 0: - # The c.CIf-family spellings were removed: report the replacement. - # (There is no runtime fallback: compile-time conditions use cif/celif/celse.) - 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 - elif is_coro_mod != 0 and string.strcmp(func_name, "coro_run") == 0: + if is_coro_mod != 0: + if string.strcmp(func_name, "coro_run") == 0: # coro.coro_run(frame): inline translation (resume loop until done, returns the ret slot). - # Note: translate_coro_* take (builder, pool, mod, cl, trans), unlike the c.* branches. + # Note: translate_coro_* take (builder, pool, mod, cl, trans). return self.Gen.AsyncGen.translate_coro_run(builder, pool, mod, cl, trans) - elif is_coro_mod != 0 and string.strcmp(func_name, "coro_destroy") == 0: + elif string.strcmp(func_name, "coro_destroy") == 0: # coro.coro_destroy(frame): return the frame to the pool (M7 free-list) return self.Gen.AsyncGen.translate_coro_destroy(builder, pool, mod, cl, trans) - elif is_coro_mod != 0 and string.strcmp(func_name, "coro_exception") == 0: + elif string.strcmp(func_name, "coro_exception") == 0: # coro.coro_exception(frame): return the frame exc slot (M4) return self.Gen.AsyncGen.translate_coro_exception(builder, pool, mod, cl, trans) - elif is_coro_mod != 0 and string.strcmp(func_name, "coro_exception_msg") == 0: + elif string.strcmp(func_name, "coro_exception_msg") == 0: # coro.coro_exception_msg(frame): return the frame msg slot (M7) return self.Gen.AsyncGen.translate_coro_exception_msg(builder, pool, mod, cl, trans) - elif is_coro_mod != 0 and string.strcmp(func_name, "coro_gather") == 0: + elif string.strcmp(func_name, "coro_gather") == 0: # coro.coro_gather(frames...): advance all coroutines concurrently (M4) return self.Gen.AsyncGen.translate_coro_gather(builder, pool, mod, cl, trans) return None @@ -362,112 +336,15 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): return None def _tc_h4_type_casts(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, mod: mlirlite.LLVMModule*, cl: ast.Call*, funcs_ptr: rawptr, func_count: int, trans: HT.Translator*, func_name: str, cargs: list[ast.AST*]*, can: sizet) -> mlirlite.Value*: - """t.XXX / typedef type casts; returns None when unmatched.""" - # Detect t.XXX type casts (uint64(ptr), rawptr(val), int(val), ...): when func is t.XXX and - # XXX is a known type, treat it as a cast; once confirmed, never fall through to cross-module calls. - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - tc_at: ast.Attribute* = ast.Attribute*(cl.func) - if tc_at.value is not None and tc_at.value.kind() == ast.ASTKind.Name: - tc_mod_nm: ast.Name* = ast.Name*(tc_at.value) - if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0: - # t.CType(value, TypeName, rawptr) casts value to TypeName*; TypeName is a type - # name (not a value), so it must be handled explicitly or it falls through to a FATAL. - if string.strcmp(func_name, "CType") == 0 and can >= 2: - cty_node: ast.AST* = cargs.get(1) - ctype_target: mlirlite.LLVMType* = None - if cty_node is not None: - cti_imp: str = None - cti_fi: str = None - if trans is not None: - cti_imp = trans._imported_modules - cti_fi = trans._from_imports - ctype_target = self.Gen.TypeGenResolve.resolve_annotation_type(pool, cty_node, cti_imp, cti_fi, trans, 0) - if ctype_target is not None: - if can == 3: - cty_arg3: ast.AST* = cargs.get(2) - cty_is_cptr: int = 0 - if cty_arg3 is not None: - # Form 1: rawptr (Attribute) - if cty_arg3.kind() == ast.ASTKind.Attribute: - cty_at3: ast.Attribute* = ast.Attribute*(cty_arg3) - if cty_at3.attr is not None and string.strcmp(cty_at3.attr, "CPtr") == 0: - if cty_at3.value is not None and cty_at3.value.kind() == ast.ASTKind.Name: - cty_nm3: ast.Name* = ast.Name*(cty_at3.value) - if cty_nm3.id is not None and string.strcmp(cty_nm3.id, "t") == 0: cty_is_cptr = 1 - # Form 2: bare CPtr - elif cty_arg3.kind() == ast.ASTKind.Name: - cty_bn3: ast.Name* = ast.Name*(cty_arg3) - if cty_bn3.id is not None and string.strcmp(cty_bn3.id, "CPtr") == 0: cty_is_cptr = 1 - if cty_is_cptr != 0: - # CVoid* -> i8* (void* is represented as i8* in LLVM) - match ctype_target: - case mlirlite.LLVMType.Void(): - ctype_target = mlirlite.Int8(pool) - case _: - pass - ctype_target = mlirlite.Ptr(pool, ctype_target) - cty_arg0: ast.AST* = cargs.get(0) - if cty_arg0 is not None: - cty_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cty_arg0, funcs_ptr, func_count, trans) - if cty_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cty_val, ctype_target, cty_arg0, trans) - # t.CType confirmed: even if type resolution fails, do not fall through to a cross-module FATAL - return None - # CConst is a const marker: CConst(val, rawptr) -> Ptr(i8) (const void*). Without - # this it emits an undefined @CConst; single-arg CConst(x) returns the value unchanged. - if string.strcmp(func_name, "CConst") == 0: - if can >= 2: - cconst_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool)) - cconst_arg: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) - if cconst_arg is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, cconst_arg, cconst_ptr_ty, cargs.get(0), trans) - elif can == 1: return self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) - return None - target_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name) - if target_ty is not None: - tc_effective_can: sizet = can - # Two-arg form: int(val, rawptr) -> Ptr(target_ty). void* is illegal in LLVM, - # so CVoid* must be represented as i8*. - if can == 2: - tc_arg2_node: ast.AST* = cargs.get(1) - tc_arg2_is_cptr: int = 0 - if tc_arg2_node is not None: - # Form 1: rawptr (Attribute form) - if tc_arg2_node.kind() == ast.ASTKind.Attribute: - tc_arg2_at: ast.Attribute* = ast.Attribute*(tc_arg2_node) - if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0: - if tc_arg2_at.value is not None and tc_arg2_at.value.kind() == ast.ASTKind.Name: - tc_arg2_nm: ast.Name* = ast.Name*(tc_arg2_at.value) - if tc_arg2_nm.id is not None and string.strcmp(tc_arg2_nm.id, "t") == 0: tc_arg2_is_cptr = 1 - # Form 2: bare CPtr (usable after `from t import CPtr`, e.g. t.CXXX(x, CPtr)) - elif tc_arg2_node.kind() == ast.ASTKind.Name: - tc_arg2_bn: ast.Name* = ast.Name*(tc_arg2_node) - if tc_arg2_bn.id is not None and string.strcmp(tc_arg2_bn.id, "CPtr") == 0: tc_arg2_is_cptr = 1 - if tc_arg2_is_cptr != 0: - # CVoid* -> i8* (void* is represented as i8* in LLVM) - match target_ty: - case mlirlite.LLVMType.Void(): - target_ty = mlirlite.Int8(pool) - case _: - pass - target_ty = mlirlite.Ptr(pool, target_ty) - tc_effective_can = 1 - if tc_effective_can == 1: - tc_arg_node: ast.AST* = cargs.get(0) - if tc_arg_node is not None: - # Pass target_ty as the 8th arg: otherwise constants pick their width from - # the i32 range and uint64(-1) materializes as i32 -1 then zext (N1). - tc_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, tc_arg_node, None, 0, trans, target_ty) - if tc_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, tc_arg_val, target_ty, tc_arg_node, trans) - # t.XXX cast confirmed but arg shape unsupported: return None, do not fall through to FATAL - return None - + """Builtin / typedef type casts; returns None when unmatched.""" # Module-qualified typedef cast (posix.mode_t(mode), win32.win32base.HANDLE(v), ...): func is # Attribute(Name(module), typedef); non-typedef names still go to the module function call. if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: mt_at: ast.Attribute* = ast.Attribute*(cl.func) if mt_at.value is not None and mt_at.value.kind() == ast.ASTKind.Name: mt_mod_nm: ast.Name* = ast.Name*(mt_at.value) - if mt_mod_nm.id is not None and string.strcmp(mt_mod_nm.id, "t") != 0 and string.strcmp(mt_mod_nm.id, "c") != 0: - mod_td_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_t_type(pool, func_name) + if mt_mod_nm.id is not None: + mod_td_ty: mlirlite.LLVMType* = self.Gen.TypeGenResolve.map_builtin_type(pool, func_name) if mod_td_ty is None: mod_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(func_name) if mod_td_str is not None and self.Gen.TypeGenCType.is_ctypedef_found() != 0: @@ -483,26 +360,26 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): mt_arg_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans, mod_td_ty) if mt_arg_val is not None: return self.Gen.CallGenCtor._translate_t_type_cast(pool, builder, mt_arg_val, mod_td_ty, cargs.get(0), trans) - # Bare typedef casts (BYTEPTR, HANDLE, CHARPTR, ...): all CTypedef names and t/c primitives + # Bare typedef casts (BYTEPTR, HANDLE, CHARPTR, ...): all CTypedef names and builtin primitives # are castable. In generic contexts T(x) first resolves T, then goes through resolve_typedef_or_map. if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: bare_fn_name: str = self.Gen.TypeGenBase.resolve_generic_type_name(func_name) bare_ty: mlirlite.LLVMType* = None - # Builtin names resolved from generic context (T->"double"/"float"): map_t_type only knows - # t.CDouble, and float must map to t.CFloat (f32), not f64. + # Builtin names resolved from generic context (T->"double"/"float"): float must map to + # f32, not f64. if string.strcmp(bare_fn_name, "double") == 0: bare_ty = mlirlite.Double(pool) elif string.strcmp(bare_fn_name, "float") == 0: bare_ty = mlirlite.Float(pool) else: # Prefer the CTypedef dynamic table (library typedef casts); on miss fall back to - # map_t_type, which (after phase-2 convergence) no longer contains stdint aliases. + # map_builtin_type. bare_imp_c: str = None bare_fi_c: str = None if trans is not None: bare_imp_c = trans._imported_modules bare_fi_c = trans._from_imports bare_ty = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, bare_fn_name, bare_imp_c, bare_fi_c) - # Names substituted from generic context (T->"int") are unknown to map_t_type, so fall - # back to resolve_annotation_type (supports t.CXxx / struct class names / aliases). + # Names substituted from generic context (T->"int") are unknown to map_builtin_type, so fall + # back to resolve_annotation_type (supports builtin names / struct class names / aliases). if bare_ty is None and string.strcmp(bare_fn_name, func_name) != 0: gp_ast: ast.AST* = self.Gen.TypeGenResolve._parse_type_string(pool, bare_fn_name, 0) if gp_ast is not None: @@ -518,17 +395,10 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): bare_arg2_node: ast.AST* = cargs.get(1) bare_arg2_is_cptr: int = 0 if bare_arg2_node is not None: - # Form 1: rawptr (Attribute form) - if bare_arg2_node.kind() == ast.ASTKind.Attribute: - bare_arg2_at: ast.Attribute* = ast.Attribute*(bare_arg2_node) - if bare_arg2_at.attr is not None and string.strcmp(bare_arg2_at.attr, "CPtr") == 0: - if bare_arg2_at.value is not None and bare_arg2_at.value.kind() == ast.ASTKind.Name: - bare_arg2_nm: ast.Name* = ast.Name*(bare_arg2_at.value) - if bare_arg2_nm.id is not None and string.strcmp(bare_arg2_nm.id, "t") == 0: bare_arg2_is_cptr = 1 - # Form 2: bare CPtr (usable after `from t import CPtr`) - elif bare_arg2_node.kind() == ast.ASTKind.Name: + # Builtin pointer marker: CPtr / rawptr + if bare_arg2_node.kind() == ast.ASTKind.Name: 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, "CPtr") == 0: bare_arg2_is_cptr = 1 + if bare_arg2_bn.id is not None and (string.strcmp(bare_arg2_bn.id, "CPtr") == 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) match bare_ty: @@ -668,8 +538,8 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if szf_mod is not None: string.strncpy(szf_mod, sz_full_name, szf_mod_len) szf_mod[szf_mod_len] = '\0' - # Exempt t/c builtins (int etc. are already handled by the builtin/size table) - if string.strcmp(szf_mod, "t") != 0 and string.strcmp(szf_mod, "c") != 0: + # Module-qualified builtin names are already handled by the builtin/size table. + if szf_mod is not None: szf_sha1: str = self.Gen.StructGen._resolve_module_sha1(szf_mod, trans._from_imports if trans is not None else None) if szf_sha1 is not None: szf_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(sz_cls_name, szf_sha1) @@ -1247,8 +1117,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase): if expr_root is not None and expr_root.kind() == ast.ASTKind.Name: expr_root_nm: str = ast.Name*(expr_root).id if expr_root_nm is not None: - if string.strcmp(expr_root_nm, "t") == 0 or string.strcmp(expr_root_nm, "c") == 0: is_mod_path_expr = 1 - elif trans._imported_modules is not None: + if trans._imported_modules is not None: if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, expr_root_nm) != 0: is_mod_path_expr = 1 if evk != ast.ASTKind.Name and is_mod_path_expr == 0: # Translate the receiver expression (the result should be Ptr(Struct)) diff --git a/App/lib/core/Gen/Call/CallGenMixin.vp b/App/lib/core/Gen/Call/CallGenMixin.vp index a90e2cc..f05a9f0 100644 --- a/App/lib/core/Gen/Call/CallGenMixin.vp +++ b/App/lib/core/Gen/Call/CallGenMixin.vp @@ -1291,8 +1291,8 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase): viperlib.snprintf(mangled, mangled_len, "%s.%s", mod_sha1, func_name) call_name = mangled else: - # t and c are internal libraries exempt from SHA1 lookup: use bare-name calls. - if string.strcmp(xmod_path, "t") == 0 or string.strcmp(xmod_path, "c") == 0: call_name = func_name + # Only real modules reach this path; a missing module segment falls back to a bare name. + if xmod_path is None: call_name = func_name else: # Check whether it is an imported module name (e.g. BuildPipeline.run_pipeline): if imported # but its SHA1 is unregistered the module was not compiled, so error out instead of a misleading from_imports lookup. diff --git a/App/lib/core/Gen/Class/ClassGenBase.vp b/App/lib/core/Gen/Class/ClassGenBase.vp index a64bd39..e284617 100644 --- a/App/lib/core/Gen/Class/ClassGenBase.vp +++ b/App/lib/core/Gen/Class/ClassGenBase.vp @@ -147,11 +147,7 @@ novirtual class ClassGenBase: while alias_orig[og_len_ce] != ' ' and alias_orig[og_len_ce] != '\0': og_len_ce += 1 if og_len_ce == 5 and string.strncmp(alias_orig, "CEnum", 5) == 0: return 1 return 0 - # Attribute(t.CEnum) form. - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: return 1 - return 0 + # Attribute form was retired together with the t module prefix. return 0 def _is_enum_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """Return 1 if the ClassDef is a CEnum (subclasses t.CEnum or uses @t.CEnum).""" @@ -185,11 +181,7 @@ novirtual class ClassGenBase: while alias_orig[og_len_cu] != ' ' and alias_orig[og_len_cu] != '\0': og_len_cu += 1 if og_len_cu == 6 and string.strncmp(alias_orig, "CUnion", 6) == 0: return 1 return 0 - # Attribute(t.CUnion) form. - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: return 1 - return 0 + # Attribute form was retired together with the t module prefix. return 0 def _is_union_class(self, cd: ast.ClassDef*, trans: HT.Translator* = None) -> int: """Return 1 if the ClassDef is a CUnion (subclasses t.CUnion or uses @t.CUnion).""" @@ -223,11 +215,7 @@ novirtual class ClassGenBase: 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(t.REnum) form. - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(base_node) - if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: return 1 - return 0 + # Attribute form was retired together with the t module prefix. return 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).""" @@ -245,7 +233,7 @@ novirtual class ClassGenBase: if self._is_crenum_base(base_node, trans) == 1: return 1 return 0 def _has_decorator(self, decorator_list: list[ast.AST*]*, deco_name: str) -> int: - """Return 1 if decorator_list contains the given decorator name.""" + """Return 1 if decorator_list contains the given bare builtin decorator name.""" if decorator_list is None: return 0 dn: sizet = len(decorator_list) if dn == 0: return 0 @@ -253,16 +241,7 @@ novirtual class ClassGenBase: deco: ast.AST* = decorator_list.get(di) if deco is None: continue k: int = deco.kind() - # @t.NoVTable form (Attribute). - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(deco) - if at.attr is not None and string.strcmp(at.attr, deco_name) == 0: - # Check that value is Name('t'). - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: return 1 - return 0 - # @NoVTable form (Name; from t import NoVTable). + # @NoVTable / @CVTable / @TLS / @CStatic form (bare builtin Name). if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(deco) if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: return 1 @@ -290,10 +269,10 @@ novirtual class ClassGenBase: k: int = deco.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) - # @c.Attribute(t.attr.xxx) form: func is Attribute(c, "Attribute"). - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue - at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + # @Attribute(attr.xxx) form: func is the bare builtin Name("Attribute"). + if cl.func is None or cl.func.kind() != ast.ASTKind.Name: continue + at0: ast.Name* = ast.Name*(cl.func) + if at0.id is None or string.strcmp(at0.id, "Attribute") != 0: continue if cl.args is None: continue an: sizet = len(cl.args) for ai in range(int(an)): @@ -319,7 +298,7 @@ novirtual class ClassGenBase: return int(cn.int_val) return 0 def _class_aligned_value(self, decorator_list: list[ast.AST*]*) -> int: - """Return the alignment bytes from @c.Attribute(t.attr.aligned(N)); 0 when absent.""" + """Return the alignment bytes from @Attribute(attr.aligned(N)); 0 when absent.""" if decorator_list is None: return 0 dn: sizet = len(decorator_list) if dn == 0: return 0 @@ -328,9 +307,9 @@ novirtual class ClassGenBase: if deco is None: continue if deco.kind() == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(deco) - if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: continue - at0: ast.Attribute* = ast.Attribute*(cl.func) - if at0.attr is None or string.strcmp(at0.attr, "Attribute") != 0: continue + if cl.func is None or cl.func.kind() != ast.ASTKind.Name: continue + at0: ast.Name* = ast.Name*(cl.func) + if at0.id is None or string.strcmp(at0.id, "Attribute") != 0: continue if cl.args is None: continue an: sizet = len(cl.args) for ai in range(int(an)): @@ -366,9 +345,6 @@ novirtual class ClassGenBase: vn: ast.Name* = ast.Name*(at.value) is_prop_name: int = 0 if vn.id is not None and string.strcmp(vn.id, "property") == 0: is_prop_name = 1 - # @t.TLS one-time init marker (mirrors TPC HandlesFunctions): - # value must be Name('t'); bare @TLS is handled by the Name branch. - if vn.id is not None and string.strcmp(vn.id, "t") == 0 and string.strcmp(at.attr, "TLS") == 0: meta |= META_TLS # Recognize @property.setter and @x.setter/getter/deleter. if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0: if string.strcmp(at.attr, "setter") == 0: meta |= GenTypes.META_PROP_SETTER diff --git a/App/lib/core/Gen/Class/ClassGenEnum.vp b/App/lib/core/Gen/Class/ClassGenEnum.vp index 806c6d8..864c733 100644 --- a/App/lib/core/Gen/Class/ClassGenEnum.vp +++ b/App/lib/core/Gen/Class/ClassGenEnum.vp @@ -42,7 +42,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # [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 (CTypedef dynamic table first, fall back to map_t_type) + # Other t.CXxx types: unified (CTypedef dynamic table first, fall back to map_builtin_type) 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 @@ -266,7 +266,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): tgt: ast.Name* = ast.Name*(aa.target) if tgt.id is None: continue - # [enum spec fail-fast] Members may not be pointer types: t.CPtr / CRef / + # [enum spec fail-fast] Members may not be pointer types: rawptr / CRef / # CTempRef / CAutoPtr / rawptr[...] / str / bytes and unions carrying a pointer. Checked before type resolution. if self._enum_member_annotation_is_ptr(aa.annotation) == 1: self.Gen.TypeGenErr.fatal_error(aa, f"enum member '{tgt.id}' cannot be a pointer type (enum values only support integer member types)", "TypeError") @@ -601,6 +601,18 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # analysis; the hardcoded size table below is only a fallback for t/c core primitives. dyn_sz: int = self.Gen.TypeGenResolve.get_type_size_bytes(pool, type_name, None, None) if dyn_sz > 0: return dyn_sz + # Builtin short names + if string.strcmp(type_name, "sizet") == 0 or string.strcmp(type_name, "size_t") == 0: return 8 + if string.strcmp(type_name, "int8") == 0 or string.strcmp(type_name, "uint8") == 0: return 1 + if string.strcmp(type_name, "uchar") == 0: return 1 + if string.strcmp(type_name, "int16") == 0 or string.strcmp(type_name, "uint16") == 0: return 2 + if string.strcmp(type_name, "short") == 0 or string.strcmp(type_name, "ushort") == 0: return 2 + if string.strcmp(type_name, "int32") == 0 or string.strcmp(type_name, "uint32") == 0: return 4 + if string.strcmp(type_name, "int") == 0 or string.strcmp(type_name, "uint") == 0: return 4 + if string.strcmp(type_name, "long") == 0 or string.strcmp(type_name, "ulong") == 0: return 4 + if string.strcmp(type_name, "int64") == 0 or string.strcmp(type_name, "uint64") == 0: return 8 + if string.strcmp(type_name, "longlong") == 0 or string.strcmp(type_name, "ulonglong") == 0: return 8 + 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 @@ -793,7 +805,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase): # Register into HandlesStruct. # A forward-declared placeholder for THIS class may have been created *during the variant walk* - # above: a variant field like `Pointee: LLVMType*` is `BinOp(LLVMType | t.CPtr)` (parser's + # above: a variant field like `Pointee: LLVMType*` is `BinOp(LLVMType | rawptr)` (parser's # _make_ptr_type expands the C-style suffix into a union, NOT into `rawptr[...]`), so resolving it # resolves the class name and calls ensure_forward_class. register_struct de-duplicates by Ty # pointer, so it would add a SECOND same-named entry and get_struct_type/find_struct (first match diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index 997b59c..2e41b5c 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -318,10 +318,10 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): if sign == TSpec.TS_SIGN_SIGNED: return "int64" return None # ---- Floats: exact bit width (no signedness concept, unambiguous) ---- - if string.strcmp(buf, "half") == 0: return "t.CFloat16T" + if string.strcmp(buf, "half") == 0: return "float16" if string.strcmp(buf, "float") == 0: return "float" if string.strcmp(buf, "double") == 0: return "double" - if string.strcmp(buf, "fp128") == 0: return "t.CFloat128T" + if string.strcmp(buf, "fp128") == 0: return "float128" return None def infer_scalar_type_arg_from_llvm_ty(self, pool: memhub.MemBuddy*, ty: mlirlite.LLVMType*, sign: int) -> str: diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 6f4102e..a71d8a7 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -694,7 +694,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase): arg_m: ast.Arg* = ast.Arg*(alist.get(ai_m)) mm: int = 0 if arg_m is not None and arg_m.annotation is not None: - if self.Gen.TypeGenResolve._is_t_attr(arg_m.annotation, "CVoid", imported_modules) == 0: + if self.Gen.TypeGenResolve._is_builtin_marker(arg_m.annotation, "CVoid", imported_modules) == 0: mm = self.Gen.TypeGenResolve.ref_param_mode(arg_m.annotation, imported_modules) if mm == 1: mode_buf[mode_cnt] = char(49) elif mm == 2: mode_buf[mode_cnt] = char(50) diff --git a/App/lib/core/Gen/Expr/ExprGenAttr.vp b/App/lib/core/Gen/Expr/ExprGenAttr.vp index 0d433a1..3a10d87 100644 --- a/App/lib/core/Gen/Expr/ExprGenAttr.vp +++ b/App/lib/core/Gen/Expr/ExprGenAttr.vp @@ -65,6 +65,42 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): def _is_t_type_object_name(self, name: str) -> int: """Check whether name is a t.py type-object name (CPtr/CInt/CDouble, ...).""" if name is None: return 0 + # builtin short type names (int8/uint64/sizet/...) + if string.strcmp(name, "sizet") == 0: return 1 + if string.strcmp(name, "size_t") == 0: return 1 + if string.strcmp(name, "int8") == 0: return 1 + if string.strcmp(name, "int16") == 0: return 1 + if string.strcmp(name, "int32") == 0: return 1 + if string.strcmp(name, "int64") == 0: return 1 + if string.strcmp(name, "uint8") == 0: return 1 + if string.strcmp(name, "uint16") == 0: return 1 + if string.strcmp(name, "uint32") == 0: return 1 + if string.strcmp(name, "uint64") == 0: return 1 + if string.strcmp(name, "intfast8") == 0: return 1 + if string.strcmp(name, "intfast16") == 0: return 1 + if string.strcmp(name, "intfast32") == 0: return 1 + if string.strcmp(name, "intfast64") == 0: return 1 + if string.strcmp(name, "uintfast8") == 0: return 1 + if string.strcmp(name, "uintfast16") == 0: return 1 + if string.strcmp(name, "uintfast32") == 0: return 1 + if string.strcmp(name, "uintfast64") == 0: return 1 + if string.strcmp(name, "intleast8") == 0: return 1 + if string.strcmp(name, "intleast16") == 0: return 1 + if string.strcmp(name, "intleast32") == 0: return 1 + if string.strcmp(name, "intleast64") == 0: return 1 + if string.strcmp(name, "uintleast8") == 0: return 1 + if string.strcmp(name, "uintleast16") == 0: return 1 + if string.strcmp(name, "uintleast32") == 0: return 1 + if string.strcmp(name, "uintleast64") == 0: return 1 + if string.strcmp(name, "uchar") == 0: return 1 + if string.strcmp(name, "short") == 0: return 1 + if string.strcmp(name, "ushort") == 0: return 1 + if string.strcmp(name, "uint") == 0: return 1 + if string.strcmp(name, "long") == 0: return 1 + if string.strcmp(name, "ulong") == 0: return 1 + if string.strcmp(name, "longlong") == 0: return 1 + if string.strcmp(name, "ulonglong") == 0: return 1 + if string.strcmp(name, "ptrdifft") == 0: return 1 # type object names in t.py (PascalCase, initial uppercase) if string.strcmp(name, "CPtr") == 0: return 1 if string.strcmp(name, "CInt") == 0: return 1 @@ -217,36 +253,16 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): if use_ty is None: use_ty = mlirlite.Int8(pool) # ensure cross-module struct types in use_ty have an opaque declaration mlirlite.module_ensure_opaque_for_type(mod, pool, use_ty) - # special case: type objects in t.py (CPtr/CInt/CDouble etc.). t.py is not compiled but - # these objects are referenced at runtime, so emit a linkonce_odr definition with null init. - is_t_type_obj: int = 0 - if string.strcmp(mod_path_w, "t") == 0: is_t_type_obj = self._is_t_type_object_name(at.attr) # a class name is not a module-level global: registered classes/structs/REnums are always # handled by the class/REnum paths, never manufactured into an external global here. - if is_t_type_obj == 0 and self.Gen.StructGen.find_struct(at.attr) is not None: return None - # fallback declaration name: t type objects (t.py uncompiled, no sha1) keep the bare - # linkonce_odr name; other module attributes carry the target module's SHA1 prefix. - gv_name_ba: str = at.attr - if is_t_type_obj == 0: gv_name_ba = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr) + if self.Gen.StructGen.find_struct(at.attr) is not None: return None + # fallback declaration name: other module attributes carry the target module's SHA1 prefix. + gv_name_ba: str = self.Gen.FuncGenBase._mangle_name_with_sha1(self._lookup_module_sha1(mod_path_w), at.attr) ext_gv: mlirlite.GlobalVariable* = mlirlite.new_global_variable(pool, gv_name_ba, use_ty) if ext_gv is not None: - if is_t_type_obj != 0: - # t.CPtr etc.: create a definition with a null initializer (linkonce_odr) - ext_gv.Linkage = "linkonce_odr" - # initializer text for i8* null - null_init: bytes = pool.alloc(8) - if null_init is not None: - null_init[0] = 'n' - null_init[1] = 'u' - null_init[2] = 'l' - null_init[3] = 'l' - null_init[4] = '\0' - ext_gv.Initializer = null_init - else: ext_gv.Initializer = None - else: - # regular module attribute: external declaration (definition provided elsewhere) - ext_gv.Linkage = "external" - ext_gv.Initializer = None + # regular module attribute: external declaration (definition provided elsewhere) + ext_gv.Linkage = "external" + ext_gv.Initializer = None mlirlite.module_add_global(mod, ext_gv) return self.make_global_ref(pool, gv_name_ba, use_ty) def _lookup_module_sha1(self, mod_name: str) -> str: @@ -256,32 +272,19 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): # module attribute (sys._mbuddy → global), then struct field (GEP + load). Name bases skip the struct load. - # _get_cderef_attr_base - base pointer of a c.Deref(ptr).attr access (like *p.a → p->a): return the ptr - # itself, not the loaded struct value; None for non-c.Deref forms (_deref_if_ptr_ptr resolves the level). + # _get_cderef_attr_base - base pointer of a `(*ptr).attr` access (like p->a): return the ptr + # itself, not the loaded struct value; None for non-deref forms (_deref_if_ptr_ptr resolves the level). def _get_cderef_attr_base(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, at_value: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: - """Return the ptr itself for a dereferenced attribute base (`c.Deref(ptr).attr` / `(*ptr).attr`), else None (no load).""" + """Return the ptr itself for a dereferenced attribute base (`(*ptr).attr`), else None (no load).""" if at_value is None: return None - # New syntax form: `(*ptr).attr` is AST UnaryOp(OpKind.Deref) — identical semantics to the legacy - # `c.Deref(ptr).attr`. Without this branch the attribute write path sees a *loaded struct value* - # as the base and fails with "base=非指针类型,无法做属性写入"; the read path silently does an - # extra struct load. Both must GEP the pointer itself (R4 migration of `c.Deref` -> `*`). + # `(*ptr).attr` is AST UnaryOp(OpKind.Deref). Without this branch the attribute write path + # sees a *loaded struct value* as the base; both paths must GEP the pointer itself. if at_value.kind() == ast.ASTKind.UnaryOp: uo_cd: ast.UnaryOp* = ast.UnaryOp*(at_value) if uo_cd.op != ast.OpKind.Deref or uo_cd.operand is None: return None inner_uo: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_cd.operand, None, 0, trans) if inner_uo is not None and self.is_ptr_type(inner_uo.Ty) != 0: return inner_uo return None - if at_value.kind() != ast.ASTKind.Call: return None - cl_cd: ast.Call* = ast.Call*(at_value) - if cl_cd.func is None or cl_cd.func.kind() != ast.ASTKind.Attribute: return None - f_cd: ast.Attribute* = ast.Attribute*(cl_cd.func) - if f_cd.attr is None or string.strcmp(f_cd.attr, "Deref") != 0: return None - if f_cd.value is None or f_cd.value.kind() != ast.ASTKind.Name: return None - nm_cd: ast.Name* = ast.Name*(f_cd.value) - if nm_cd.id is None or string.strcmp(nm_cd.id, "c") != 0: return None - if cl_cd.args is None or len(cl_cd.args) < 1: return None - inner_cd: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cl_cd.args.get(0), None, 0, trans) - if inner_cd is not None and self.is_ptr_type(inner_cd.Ty) != 0: return inner_cd return None def translate_attribute(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*: """Translate an attribute access and return the loaded field value.""" @@ -482,7 +485,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase): return None # it is a submodule, hand it to the nested attribute path # special case: t.ASM_DESCR is the inline-asm constraint namespace, not a CDefine; its # .XXX is handled by _asm_resolve_constraint, so return None for the nested path to handle. - if string.strcmp(nm_ma.id, "t") == 0 and string.strcmp(at.attr, "ASM_DESCR") == 0: return None + if string.strcmp(nm_ma.id, "ASM_DESCR") == 0 and string.strcmp(at.attr, "ASM_DESCR") == 0: return None # ALL_CAPS module attribute that is not a CDefine: load it as a cross-module global when the # module defines a same-named global (e.g. PA_DEPS_MAX_STR); else fail-fast (undefined value). if self.Gen.ExprGenCdef._is_cdefine_name_pattern(at.attr) != 0: diff --git a/App/lib/core/Gen/Expr/ExprGenCdef.vp b/App/lib/core/Gen/Expr/ExprGenCdef.vp index 8970683..58df8c3 100644 --- a/App/lib/core/Gen/Expr/ExprGenCdef.vp +++ b/App/lib/core/Gen/Expr/ExprGenCdef.vp @@ -328,12 +328,11 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase): if match_ok == 0: continue if pyi_buf[line_start + name_len] != ':': continue - # check the line contains "t.CDefine" - # scan the line for "t.CDefine" + # check the line contains the CDefine marker has_cdefine: int = 0 ci: sizet = line_start + name_len + 1 - while ci + 8 <= line_start + line_len: - if (pyi_buf[ci] == 't' and pyi_buf[ci + 1] == '.' and pyi_buf[ci + 2] == 'C' and pyi_buf[ci + 3] == 'D' and pyi_buf[ci + 4] == 'e' and pyi_buf[ci + 5] == 'f' and pyi_buf[ci + 6] == 'i' and pyi_buf[ci + 7] == 'n' and pyi_buf[ci + 8] == 'e'): + while ci + 7 <= line_start + line_len: + if (pyi_buf[ci] == 'C' and pyi_buf[ci + 1] == 'D' and pyi_buf[ci + 2] == 'e' and pyi_buf[ci + 3] == 'f' and pyi_buf[ci + 4] == 'i' and pyi_buf[ci + 5] == 'n' and pyi_buf[ci + 6] == 'e'): has_cdefine = 1 break ci += 1 diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index 34da536..849e078 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -201,13 +201,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): k: int = node.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(cl.func) - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name* = ast.Name*(at.value) - if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0 and at.attr is not None: - if self._type_name_unsigned(at.attr) != 0: return 1 - return 0 + if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: return 0 # Plain function call: widen by the callee's **declared return type**. Without this, # `uint64(f())` with `def f() -> uint32` emitted `sext i32 -> i64` (verified in the # generated IR), so a u32 with bit 31 set grew 0xFFFFFFFF in the high half — a real @@ -359,13 +353,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): k: int = node.kind() if k == ast.ASTKind.Call: cl: ast.Call* = ast.Call*(node) - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(cl.func) - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name* = ast.Name*(at.value) - if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0 and at.attr is not None: - if self._spec_sign_from_annot(at.attr) == TSpec.TS_SIGN_SIGNED: return 1 - return 0 + if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None: diff --git a/App/lib/core/Gen/Func/FuncGenBase.vp b/App/lib/core/Gen/Func/FuncGenBase.vp index e31211f..b6176df 100644 --- a/App/lib/core/Gen/Func/FuncGenBase.vp +++ b/App/lib/core/Gen/Func/FuncGenBase.vp @@ -42,23 +42,12 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): call_node: ast.Call* = ast.Call*(deco) if call_node.func is None: continue cfk: int = call_node.func.kind() - if cfk != ast.ASTKind.Attribute: continue - # Detect c.Attribute - func_attr: ast.Attribute* = ast.Attribute*(call_node.func) - if func_attr.attr is None: continue - if string.strcmp(func_attr.attr, "Attribute") != 0: continue - if func_attr.value is None: continue - fvk: int = func_attr.value.kind() - if fvk != ast.ASTKind.Name: continue - c_name: ast.Name* = ast.Name*(func_attr.value) - if c_name.id is None: continue - if string.strcmp(c_name.id, "c") != 0: continue - # 不要求 `import c`:`@__attribute__(...)` 会被 ast/parser.vp(_DesugarMagicAttribute) - # 脱糖成 `@c.Attribute(...)`,这里的 `c.` 前缀是编译器自己产生的(用户写的是 - # `@__attribute__`,并非 `@c.Attribute`)。若在此要求 `import c`,用户明明没引入 c - # 就会把整条装饰器静默丢弃(`stackrealign`/`always_inline` 等函数属性全失效)。 - # extract_func_section 本就没有这个守卫,二者保持一致。 + # Detect the builtin Attribute(...) wrapper emitted by @__attribute__(...). + if cfk != ast.ASTKind.Name: continue + func_nm: ast.Name* = ast.Name*(call_node.func) + if func_nm.id is None: continue + if string.strcmp(func_nm.id, "Attribute") != 0: continue # Iterate args and extract attrs if call_node.args is None: continue @@ -80,7 +69,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): if found_any == 0: return None return attrs_buf def extract_func_section(self, pool: memhub.MemBuddy*, decorator_list: list[ast.AST*]*, imported_modules: str) -> str: - """Extract @c.Attribute(t.attr.section(...)) as the attr-group text.""" + """Extract @Attribute(attr.section(...)) as the attr-group text.""" if pool is None or decorator_list is None: return None dn: sizet = len(decorator_list) if dn == 0: return None @@ -88,9 +77,9 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): deco: ast.AST* = decorator_list.get(di) if deco is None or deco.kind() != ast.ASTKind.Call: continue call_node: ast.Call* = ast.Call*(deco) - if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute: continue - func_attr: ast.Attribute* = ast.Attribute*(call_node.func) - if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0: continue + if call_node.func is None or call_node.func.kind() != ast.ASTKind.Name: continue + func_nm: ast.Name* = ast.Name*(call_node.func) + if func_nm.id is None or string.strcmp(func_nm.id, "Attribute") != 0: continue if call_node.args is None: continue args_list: list[ast.AST*]* = call_node.args an: sizet = len(args_list) @@ -272,11 +261,11 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase): for ai in range(int(an)): arg: ast.Arg* = ast.Arg*(alist.get(ai)) if arg is not None and arg.arg is not None: - # t.CVoid means no args: skip + # CVoid / void means no args: skip if arg.annotation is not None: - if arg.annotation.kind() == ast.ASTKind.Attribute: - at_cf: ast.Attribute* = ast.Attribute*(arg.annotation) - if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: continue + if arg.annotation.kind() == ast.ASTKind.Name: + at_cn: ast.Name* = ast.Name*(arg.annotation) + if at_cn.id is not None and (string.strcmp(at_cn.id, "CVoid") == 0 or string.strcmp(at_cn.id, "void") == 0): continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, None, None, None, 0) diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 0b76e2b..f9ee881 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -38,7 +38,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): arg: ast.Arg* = ast.Arg*(alist.get(i)) if arg is None or arg.arg is None: continue # CVoid params are not emitted into the signature, so they must not occupy a mode slot. - if arg.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imp) != 0: continue + if arg.annotation is not None and self.Gen.TypeGenResolve._is_builtin_marker(arg.annotation, "CVoid", imp) != 0: continue m: int = 0 if arg.annotation is not None: m = self.Gen.TypeGenResolve.ref_param_mode(arg.annotation, imp) if m == 1: buf[cnt] = char(49) @@ -110,14 +110,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # Value-reference markers are parameter-only: `-> &T` fails fast (never a silent Ptr(T) return). self.Gen.TypeGenResolve.reject_ref_marker_position(fd.returns, imported_modules, "a function return type") ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0) - # A lone t.CExport return annotation is an export modifier with no real type -> Void + # A lone CExport return annotation is an export modifier with no real type -> Void # (CExport fell back to i32, forcing the tail check to return i32: mm.vp free root cause). - if fd.returns.kind() == ast.ASTKind.Attribute: - ce_at: ast.Attribute* = ast.Attribute*(fd.returns) - if ce_at.attr is not None and string.strcmp(ce_at.attr, "CExport") == 0: - if ce_at.value is not None and ce_at.value.kind() == ast.ASTKind.Name: - ce_nm: ast.Name* = ast.Name*(ce_at.value) - if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0: ret_ty = mlirlite.Void(pool) + if fd.returns.kind() == ast.ASTKind.Name: + ce_at: ast.Name* = ast.Name*(fd.returns) + if ce_at.id is not None and string.strcmp(ce_at.id, "CExport") == 0: ret_ty = mlirlite.Void(pool) if ret_ty is None and fd.returns is not None: if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0: ret_ty = mlirlite.Void(pool) # @c.CReturn decorator removed: encountering it is a compile-time error (use -> tuple[...] for multiple returns) @@ -206,7 +203,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if arg is None or arg.arg is None: continue # CVoid means empty param: skip if arg.annotation is not None: - if self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_builtin_marker(arg.annotation, "CVoid", imported_modules) != 0: continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0) @@ -280,14 +277,11 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): # Value-reference markers are parameter-only: `-> &T` fails fast (never a silent Ptr(T) return). self.Gen.TypeGenResolve.reject_ref_marker_position(fd.returns, imported_modules, "a function return type") ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, imported_modules, from_imports, trans, 0) - # A lone t.CExport return annotation is an export modifier with no real type -> Void + # A lone CExport return annotation is an export modifier with no real type -> Void # (CExport fell back to i32, forcing return i32: mm.vp free root cause). Mixed types keep the resolved result. - if fd.returns.kind() == ast.ASTKind.Attribute: - ce_at2: ast.Attribute* = ast.Attribute*(fd.returns) - if ce_at2.attr is not None and string.strcmp(ce_at2.attr, "CExport") == 0: - if ce_at2.value is not None and ce_at2.value.kind() == ast.ASTKind.Name: - ce_nm2: ast.Name* = ast.Name*(ce_at2.value) - if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0: ret_ty = mlirlite.Void(pool) + if fd.returns.kind() == ast.ASTKind.Name: + ce_at2: ast.Name* = ast.Name*(fd.returns) + if ce_at2.id is not None and string.strcmp(ce_at2.id, "CExport") == 0: ret_ty = mlirlite.Void(pool) # If the return annotation is purely a decorator marker (e.g. t.State, no real type), use void. # Must be checked before infer_return_type, which would return at least i32. @@ -412,7 +406,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): arg_e: ast.Arg* = ast.Arg*(alist_e.get(ai_e)) if arg_e is not None and arg_e.arg is not None: # CVoid means empty param: skip, do not add to the function signature - if arg_e.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: continue + if arg_e.annotation is not None and self.Gen.TypeGenResolve._is_builtin_marker(arg_e.annotation, "CVoid", imported_modules) != 0: continue param_ty_e: mlirlite.LLVMType* = i32_ty if arg_e.annotation is not None: resolved_e: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_e.annotation, imported_modules, from_imports, trans, 0) @@ -479,7 +473,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): rearg: ast.Arg* = ast.Arg*(reuse_list.get(reuse_i)) if rearg is None or rearg.arg is None: continue # CVoid means empty param: not part of the signature (mirrors the add_param loops above) - if rearg.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(rearg.annotation, "CVoid", imported_modules) != 0: continue + if rearg.annotation is not None and self.Gen.TypeGenResolve._is_builtin_marker(rearg.annotation, "CVoid", imported_modules) != 0: continue if reused_p is None: # 复用声明形参少于定义:签名与函数体必然错配,禁止静默,fail-fast self.Gen.TypeGenErr.fatal_error(rearg, f"reused declaration for '{fd.name}' has fewer parameters than the definition", "TypeError") @@ -537,7 +531,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): arg: ast.Arg* = ast.Arg*(alist.get(ai)) if arg is not None and arg.arg is not None: # CVoid means empty param: skip, do not add to the function signature - if arg.annotation is not None and self.Gen.TypeGenResolve._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: continue + if arg.annotation is not None and self.Gen.TypeGenResolve._is_builtin_marker(arg.annotation, "CVoid", imported_modules) != 0: continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: resolved: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg.annotation, imported_modules, from_imports, trans, 0) @@ -678,7 +672,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase): if arg2 is not None and arg2.arg is not None: # CVoid means empty param: skip, do not create an alloca if arg2.annotation is not None: - if self.Gen.TypeGenResolve._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_builtin_marker(arg2.annotation, "CVoid", imported_modules) != 0: continue param_ty2: mlirlite.LLVMType* = i32_ty if arg2.annotation is not None: resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0) diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 6cbef36..abd45ee 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -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_t_attr(arg_n.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_builtin_marker(arg_n.annotation, "CVoid", imported_modules) != 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_t_attr(arg_p.annotation, "CVoid", imported_modules) != 0: continue + if self.Gen.TypeGenResolve._is_builtin_marker(arg_p.annotation, "CVoid", imported_modules) != 0: continue if idx_p >= param_count: break pty2_n: mlirlite.LLVMType* = i32_ty if param_tys is not None: diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index 2dd3b3d..d5b3c83 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -86,16 +86,16 @@ def fatal_error(node: ast.AST*, msg: str, err_type: str = "SyntaxError") -> None if gg is not None: gg.TypeGenErr.fatal_error(node, msg, err_type) -# ---------------- map_t_type (delegates to TypeGenResolve.map_t_type) ---------------- -def map_t_type(pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*: - """Delegate to gen.map_t_type""" - if _g_gen is not None: _g_gen.TypeGenResolve.map_t_type(pool, type_name) +# ---------------- map_builtin_type (delegates to TypeGenResolve.map_builtin_type) ---------------- +def map_builtin_type(pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*: + """Delegate to gen.map_builtin_type""" + if _g_gen is not None: _g_gen.TypeGenResolve.map_builtin_type(pool, type_name) return None # ---------------- resolve_typedef_or_map (delegates to TypeGenResolve.resolve_typedef_or_map) ---------------- def resolve_typedef_or_map(pool: memhub.MemBuddy*, name: str, imported_modules: str, from_imports: str, trans: HT.Translator* = None) -> mlirlite.LLVMType*: - """Delegate to gen.resolve_typedef_or_map: CTypedef table first, then map_t_type.""" + """Delegate to gen.resolve_typedef_or_map: CTypedef table first, then map_builtin_type.""" if _g_gen is not None: return _g_gen.TypeGenResolve.resolve_typedef_or_map(pool, name, imported_modules, from_imports, trans) return None diff --git a/App/lib/core/Gen/ImportsGenMixin.vp b/App/lib/core/Gen/ImportsGenMixin.vp index 41b3600..2fca002 100644 --- a/App/lib/core/Gen/ImportsGenMixin.vp +++ b/App/lib/core/Gen/ImportsGenMixin.vp @@ -546,9 +546,12 @@ 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 are internal libraries exempt from includes scanning; so are ctraits (a .vpi - # compile-time macro lib) and viperbuild (a compiler builtin macro lib). - if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0 or string.strcmp(mod_name, "ctraits") == 0: 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 (a .vpi compile-time macro lib) and viperbuild (a compiler builtin macro lib) stay exempt. + if string.strcmp(mod_name, "ctraits") == 0: return 1 if string.strcmp(mod_name, "viperbuild") == 0: return 1 mod_sha1: str = StubMergerStore.LookupSha1ByModName(mod_name) if mod_sha1 is None: diff --git a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp index 5039279..9f5e6f2 100644 --- a/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp +++ b/App/lib/core/Gen/Stmt/StmtGenCifMixin.vp @@ -53,18 +53,11 @@ novirtual class StmtGenCifMixin: return 0 def _is_cif_call(self, node: ast.AST*) -> int: - """Check whether test is a cif marker call (c.@CIf family, or a bare @CIf-family name).""" + """Check whether test is a cif marker call (bare @CIf-family name).""" if node is None or node.kind() != ast.ASTKind.Call: return 0 cl: ast.Call* = ast.Call*(node) if cl.func is None: return 0 fk: int = cl.func.kind() - if fk == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(cl.func) - if at.attr is None: return 0 - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name* = ast.Name*(at.value) - if vn.id is not None and string.strcmp(vn.id, "c") == 0: return self._is_cif_attr(at.attr) - return 0 if fk == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(cl.func) if nm.id is not None and self._is_cif_attr(nm.id) != 0: return 1 diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index f4f396c..1dd1762 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -2652,7 +2652,7 @@ novirtual class StructGenMixin: if mod_buf_f is not None: string.strncpy(mod_buf_f, name, mod_len_f) mod_buf_f[mod_len_f] = '\0' - if string.strcmp(mod_buf_f, "t") != 0 and string.strcmp(mod_buf_f, "c") != 0: + if mod_buf_f is not None: # A 16-hex module segment is a SHA1 literal (e.g. "{9aab}.Scene3D", TypeGenResolve L1397-1402's sha1-prefix form): skip the store module-name lookup (store keys are module names, not sha1) and match name+sha1 exactly. # Otherwise _resolve_module_sha1("9aab") returns None and a bare-name fallback returns the first-registered wrong cross-module Scene3D entry (VKernel gfx / App gfx both define Scene3D -> wrong ownership -> ret_sha1=0ae -> Phase A _deps_pending deadlock). [C10 convergence] The module segment is exactly 16 lowercase hex = SHA1 literal: go through GenApi.is_sha1_hex16 (single source of truth). mod_hex_ok: int = GenApi.is_sha1_hex16(mod_buf_f) @@ -2905,7 +2905,7 @@ novirtual class StructGenMixin: if mod_buf_q is not None: string.strncpy(mod_buf_q, class_name, mod_len_q) mod_buf_q[mod_len_q] = '\0' - if string.strcmp(mod_buf_q, "t") != 0 and string.strcmp(mod_buf_q, "c") != 0: + if mod_buf_q is not None: # A 16-hex module segment ("{16hex}.Class", the normalized generic type-arg form) is the module SHA1; a registered class proves that module compiled, so match name+sha1 exactly without _resolve_module_sha1 (store keys are module names, so querying the sha1 is always None and would fail-fast wrongly). # [C10 convergence] The module segment is exactly 16 lowercase hex = SHA1 literal: go through GenApi.is_sha1_hex16; generic subscript dots are already skipped by _last_dot_outside_brackets, so only top-level a.b forms remain here. mod_hex_ok_q: int = GenApi.is_sha1_hex16(mod_buf_q) diff --git a/App/lib/core/Gen/Type/TypeGenCType.vp b/App/lib/core/Gen/Type/TypeGenCType.vp index c26205e..660c6c6 100644 --- a/App/lib/core/Gen/Type/TypeGenCType.vp +++ b/App/lib/core/Gen/Type/TypeGenCType.vp @@ -351,29 +351,17 @@ class TypeGenCType(TypeGenBase.TypeGenBase): vn: sizet = len(self.CTypedefVisiting) if vn > 0: self.CTypedefVisiting.pop() def _is_ctypedef_annotation(self, annotation: ast.AST*) -> int: - """Return 1 if the annotation is t.CTypedef, otherwise 0.""" + """Return 1 if the annotation is the CTypedef marker, otherwise 0.""" if annotation is None: return 0 - k_v: int = annotation.kind() - if k_v != ast.ASTKind.Attribute: return 0 - at: ast.Attribute* = ast.Attribute*(annotation) - # Use ast module accessors for field access: a direct at.attr read may emit a - # wrong GEP from the stub type and crash strcmp. - at_attr_v: str = ast.attribute_get_attr(at) - if at_attr_v is None: return 0 + if annotation.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(annotation) + nm_id_v: str = ast.name_get_id(nm) + if nm_id_v is None: return 0 # Length-bounded compare instead of strcmp: the token may lack a NUL and strcmp - # reads past the page; check byte 9 is a terminator/separator. - if string.strncmp(at_attr_v, "CTypedef", 8) != 0: return 0 - sep_ch_d: char = at_attr_v[8] + # reads past the page; check byte 8 is a terminator/separator. + if string.strncmp(nm_id_v, "CTypedef", 8) != 0: return 0 + sep_ch_d: char = nm_id_v[8] if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|': return 0 - at_val_v: ast.AST* = ast.attribute_get_value(at) - if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name: return 0 - mod_nm: ast.Name* = ast.Name*(at_val_v) - mod_id_v: str = ast.name_get_id(mod_nm) - if mod_id_v is None: return 0 - # same length-bounded compare ("t" may lack a NUL) - if string.strncmp(mod_id_v, "t", 1) != 0: return 0 - sep_ch_m: char = mod_id_v[1] - if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|': return 0 return 1 def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy*, tree: ast.AST*) -> int: """Scan top-level AST nodes and register all NAME: t.CTypedef = Type declarations.""" diff --git a/App/lib/core/Gen/Type/TypeGenErr.vp b/App/lib/core/Gen/Type/TypeGenErr.vp index 2881b35..3b814c8 100644 --- a/App/lib/core/Gen/Type/TypeGenErr.vp +++ b/App/lib/core/Gen/Type/TypeGenErr.vp @@ -140,14 +140,13 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): k: int = node.kind() - # Attribute node: t.CExtern, t.State, t.CExport, t.CInline - if k == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(node) - if at.attr is not None: - if string.strcmp(at.attr, marker_name) == 0: return 1 + # Name node: builtin markers CExtern / State / CExport / CInline / CStatic / CConst / CVolatile + if k == ast.ASTKind.Name: + nm: ast.Name* = ast.Name*(node) + if nm.id is not None and string.strcmp(nm.id, marker_name) == 0: return 1 return 0 - # BinOp node: int | t.CExtern (recurse into both children) + # BinOp node: int | CExtern (recurse into both children) if k == ast.ASTKind.BinOp: bop: ast.BinOp* = ast.BinOp*(node) if self.has_decorator_marker(bop.left, marker_name, depth + 1) != 0: return 1 @@ -298,7 +297,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase): if arg is None or arg.arg is None: continue param_ty: mlirlite.LLVMType* = i32_ty if arg.annotation is not None: - # Unified: prefer the CTypedef dynamic table, fall back to map_t_type + # Unified: prefer the CTypedef dynamic table, fall back to map_builtin_type # (stage 2 removed hardcoded aliases; BYTE etc. now rely on library typedefs) if arg.annotation.kind() == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(arg.annotation) diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 3d9857a..2e4bb58 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -266,6 +266,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # TypeGenCDef.lookup_cdefine_constant), since -1 is a valid constant. self.Gen.TypeGenCDef.lookup_cdefine_constant(name) if self.Gen.TypeGenCDef.is_cdefine_found() != 0: return 1 + if self.map_builtin_type(pool, name) is not None: return 1 if string.strcmp(name, "int") == 0: return 1 if string.strcmp(name, "char") == 0: return 1 if string.strcmp(name, "bool") == 0: return 1 @@ -278,25 +279,20 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if name[0] >= 'A' and name[0] <= 'Z': return 1 return 0 - # _is_ptr_marker_text - whether text is a bare pointer marker (t.CPtr / c.CPtr / CPtr); - # only the CPtr family counts, consistent with _is_cptr_marker. + # _is_ptr_marker_text - whether text is the builtin pointer marker (CPtr). def _is_ptr_marker_text(self, txt: str) -> int: """Whether txt is a bare pointer marker (one pointer layer): 1=yes / 0=no.""" if txt is None: return 0 if string.strcmp(txt, "CPtr") == 0: return 1 - if string.strcmp(txt, "t.CPtr") == 0: return 1 - if string.strcmp(txt, "c.CPtr") == 0: return 1 return 0 # _is_ptr_subscript_container_text - whether text is a pointer subscript container name - # (rawptr / t.rawptr / c.rawptr / CPtr); subscript forms then fold to `T*`. + # (rawptr / CPtr); subscript forms then fold to `T*`. def _is_ptr_subscript_container_text(self, txt: str) -> int: """Whether txt names a pointer subscript container (rawptr/CPtr): 1=yes / 0=no.""" if txt is None: return 0 if self._is_ptr_marker_text(txt) != 0: return 1 if string.strcmp(txt, "rawptr") == 0: return 1 - if string.strcmp(txt, "t.rawptr") == 0: return 1 - if string.strcmp(txt, "c.rawptr") == 0: return 1 return 0 # _ptr_star_text - append one pointer layer to a type-name text (base + "*"); @@ -517,20 +513,6 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): sha1c = self._class_true_def_sha1(pool, type_name, sha1c) res_c: str = self._concat_sha1_class(pool, sha1c, type_name) if res_c is not None: return res_c - # ---- 5.2 bare name from builtin t/c -> normalize to "t.X" / "c.X"; t/c have no - # module SHA1, so a bare import would otherwise split from `t.X`. - if from_imports is not None: - _bi_mod: str = self.Gen.ImportsGen.lookup_from_import(from_imports, type_name, 0) - if _bi_mod is not None: - if (string.strcmp(_bi_mod, "t") == 0 or string.strcmp(_bi_mod, "c") == 0) and self.map_t_type(pool, type_name) is not None: - _bi_len: sizet = string.strlen(_bi_mod) + 1 + string.strlen(type_name) + 1 - _bi_buf: str = pool.alloc(_bi_len) - if _bi_buf is not None: - _bi_buf[0] = '\0' - string.strcat(_bi_buf, _bi_mod) - string.strcat(_bi_buf, ".") - string.strcat(_bi_buf, type_name) - return _bi_buf # ---- 5.5 bare name that is a registered class: prefix with its defining module # SHA1; rule 5 only checks from_imports and would split specialization names. if string.strchr(type_name, '[') is None and string.strchr(type_name, '.') is None: @@ -791,7 +773,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): """Get the file currently being compiled (used for error attribution).""" return self.CurrentFile def resolve_typedef_or_map(self, pool: memhub.MemBuddy*, name: str, imported_modules: str, from_imports: str, trans: HT.Translator* = None) -> mlirlite.LLVMType*: - """Resolve a name as a CTypedef first, falling back to map_t_type.""" + """Resolve a name as a CTypedef first, falling back to map_builtin_type.""" if name is None: return None if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH: ts_rt: str = self.Gen.TypeGenCType.lookup_ctypedef(name) @@ -804,7 +786,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 self.Gen.TypeGenCType._ctypedef_pop_visiting() if ity_rt is not None: return ity_rt - # [builtins last match] After the typedef table and map_t_type both miss, check + # [builtins last match] After the typedef table and map_builtin_type both miss, check # includes/builtins.vp (e.g. rawptr: t.CTypedef = t.CPtr) and parse recursively. btd_r: str = self._lookup_builtins_typedef(pool, name) if btd_r is not None: @@ -827,7 +809,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): lib_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, lib_node, imported_modules, from_imports, trans, 1) self.Gen.TypeGenCType.CTypedefResolveDepth -= 1 if lib_ty is not None: return lib_ty - # Bare Python/C builtin aliases: map_t_type only knows the t.CXxx spelling, so + # Bare Python/C builtin aliases: map_builtin_type only knows the t.CXxx spelling, so # resolve them here to match resolve_annotation_type's bare-name branch. Without # this the two-arg form int(x, t.CPtr) misses _tc_h4 and fails fast as "int". if string.strcmp(name, "str") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) @@ -838,7 +820,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if string.strcmp(name, "float") == 0: return mlirlite.Float(pool) if string.strcmp(name, "double") == 0: return mlirlite.Double(pool) if string.strcmp(name, "void") == 0: return mlirlite.Void(pool) - return self.map_t_type(pool, name) + return self.map_builtin_type(pool, name) def get_type_size_bytes(self, pool: memhub.MemBuddy*, name: str, imported_modules: str, from_imports: str) -> int: """Return the type size in bytes via resolve_typedef_or_map, or 0 on failure.""" if name is None: return 0 @@ -962,7 +944,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): while name_l > 0 and buf[line_start + name_l - 1] == ' ': name_l -= 1 if name_l == 0 or name_l >= 128: return 0 rest: str = buf + line_start + j + 1 - if string.strstr(rest, "t.CTypedef") is None: return 0 + if string.strstr(rest, "CTypedef") is None: return 0 eq: str = string.strstr(rest, "=") if eq is None: return 0 vs = sizet(uint64(eq) - uint64(buf)) - line_start + 1 @@ -979,18 +961,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): out_buf[name_l] = '\0' # Normalize a C-style typedef RHS (`const T` / `T*`) into the canonical `|` union text, # mirroring TPC's TypeAnnotationResolver._NormalizeTypedefRhsText: leading const/volatile - # become `t.CConst |` / `t.CVolatile |`, trailing `*` runs become ` | t.CPtr`. Text without + # become `CConst |` / `CVolatile |`, trailing `*` runs become ` | CPtr`. Text without # these forms is copied verbatim (byte-identical to the pre-normalization behavior). pos: sizet = name_l + 1 k: sizet = vs while True: if k + 6 <= ve and string.strncmp(buf + line_start + k, "const", 5) == 0 and (buf[line_start + k + 5] == ' ' or buf[line_start + k + 5] == '\t'): - string.memcpy(out_buf + pos, "t.CConst | ", 11) - pos += 11 + string.memcpy(out_buf + pos, "CConst | ", 9) + pos += 9 k += 6 elif k + 9 <= ve and string.strncmp(buf + line_start + k, "volatile", 8) == 0 and (buf[line_start + k + 8] == ' ' or buf[line_start + k + 8] == '\t'): - string.memcpy(out_buf + pos, "t.CVolatile | ", 14) - pos += 14 + string.memcpy(out_buf + pos, "CVolatile | ", 12) + pos += 12 k += 9 else: break @@ -1004,16 +986,16 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): vlen2: sizet = ve2 - k if vlen2 > 190: vlen2 = 190 # Output capacity guard (register_ctypedef_from_source allocates 512 bytes for NAME\0VALUE\0). - if pos + vlen2 + ptrs * 11 > 500: - if pos + ptrs * 11 >= 500: ptrs = 0 - if pos + ptrs * 11 >= 500: vlen2 = 0 - else: vlen2 = 500 - pos - ptrs * 11 + if pos + vlen2 + ptrs * 7 > 500: + if pos + ptrs * 7 >= 500: ptrs = 0 + if pos + ptrs * 7 >= 500: vlen2 = 0 + else: vlen2 = 500 - pos - ptrs * 7 for ci2 in range(int(vlen2)): out_buf[pos + ci2] = buf[line_start + k + ci2] pos += vlen2 for pi in range(int(ptrs)): - string.memcpy(out_buf + pos, " | t.CPtr", 9) - pos += 9 + string.memcpy(out_buf + pos, " | CPtr", 7) + pos += 7 out_buf[pos] = '\0' return 1 def _lookup_builtins_typedef(self, pool: memhub.MemBuddy*, name: str) -> str: @@ -1024,10 +1006,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType.LastBuiltinsTypedefName = self.Gen.TypeGenCType.store_builtins_diag(0, name) self.Gen.TypeGenCType.LastBuiltinsTypedefResult = None # rawptr is built into the compiler (a reserved word on both TPC/VPC) and takes - # priority over any external declaration; always return t.CPtr. + # priority over any external declaration; always return CPtr. if string.strcmp(name, "rawptr") == 0: - self.Gen.TypeGenCType.LastBuiltinsTypedefResult = "t.CPtr" - return "t.CPtr" + self.Gen.TypeGenCType.LastBuiltinsTypedefResult = "CPtr" + return "CPtr" ts_b: str = self.Gen.TypeGenCType.lookup_ctypedef(name) if ts_b is not None and self.Gen.TypeGenCType.CTypedefFound != 0: # The table value may still be a module-qualified ref (size_t -> stdint.size_t); expand it @@ -1371,10 +1353,38 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if entry is None or entry.Ty is None: return None return mlirlite.Ptr(pool, entry.Ty) - def map_t_type(self, pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*: - """Map a t.CXxx / c.CXxx type name to its LLVMType. Note: str = i8* = bytes.""" + def map_builtin_type(self, pool: memhub.MemBuddy*, type_name: str) -> mlirlite.LLVMType*: + """Map a builtin type name to its LLVMType. Note: str = i8* = bytes.""" if type_name is None: return None + # Builtin short names (no import / typedef required) + if string.strcmp(type_name, "sizet") == 0 or string.strcmp(type_name, "size_t") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "int8") == 0 or string.strcmp(type_name, "intfast8") == 0 or string.strcmp(type_name, "intleast8") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "int16") == 0 or string.strcmp(type_name, "intfast16") == 0 or string.strcmp(type_name, "intleast16") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "int32") == 0 or string.strcmp(type_name, "intfast32") == 0 or string.strcmp(type_name, "intleast32") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "int64") == 0 or string.strcmp(type_name, "intfast64") == 0 or string.strcmp(type_name, "intleast64") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "uint8") == 0 or string.strcmp(type_name, "uintfast8") == 0 or string.strcmp(type_name, "uintleast8") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "uint16") == 0 or string.strcmp(type_name, "uintfast16") == 0 or string.strcmp(type_name, "uintleast16") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "uint32") == 0 or string.strcmp(type_name, "uintfast32") == 0 or string.strcmp(type_name, "uintleast32") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "uint64") == 0 or string.strcmp(type_name, "uintfast64") == 0 or string.strcmp(type_name, "uintleast64") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "uchar") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "ushort") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "uint") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "short") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "long") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "ulong") == 0: return mlirlite.Int32(pool) + elif string.strcmp(type_name, "longlong") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "ulonglong") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "ptrdifft") == 0: return mlirlite.Int64(pool) + elif string.strcmp(type_name, "intptr") == 0 or string.strcmp(type_name, "uintptr") == 0: return mlirlite.Int64(pool) + # Exact-width float / char short names (stdint aliases use these directly) + elif string.strcmp(type_name, "float8") == 0 or string.strcmp(type_name, "float16") == 0: return mlirlite.Half(pool) + elif string.strcmp(type_name, "float32") == 0: return mlirlite.Float(pool) + elif string.strcmp(type_name, "float64") == 0: return mlirlite.Double(pool) + elif string.strcmp(type_name, "float128") == 0: return mlirlite.FP128(pool) + elif string.strcmp(type_name, "char8") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "char16") == 0 or string.strcmp(type_name, "wchar") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "char32") == 0: return mlirlite.Int32(pool) # Basic integer types if string.strcmp(type_name, "CInt") == 0: return mlirlite.Int32(pool) elif string.strcmp(type_name, "CChar") == 0: return mlirlite.Int8(pool) @@ -1402,6 +1412,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): elif string.strcmp(type_name, "CFloat32T") == 0: return mlirlite.Float(pool) elif string.strcmp(type_name, "CFloat64T") == 0: return mlirlite.Double(pool) elif string.strcmp(type_name, "CFloat128T") == 0: return mlirlite.FP128(pool) + # Exact-width char types (C11 char8_t/char16_t/char32_t, Windows wchar_t = 16-bit) + elif string.strcmp(type_name, "CChar8T") == 0: return mlirlite.Int8(pool) + elif string.strcmp(type_name, "CChar16T") == 0 or string.strcmp(type_name, "CWCharT") == 0: return mlirlite.Int16(pool) + elif string.strcmp(type_name, "CChar32T") == 0: return mlirlite.Int32(pool) # Pointer / void: t.CPtr = i8*, str = i8* = str = bytes elif string.strcmp(type_name, "CPtr") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) # Unsigned function pointer: bare t.Callable -> i8* (same LLVM repr as the full @@ -1448,46 +1462,30 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): elif string.strcmp(type_name, "float") == 0: return mlirlite.Float(pool) elif string.strcmp(type_name, "double") == 0: return mlirlite.Double(pool) return None - def _is_t_attr(self, node: ast.AST*, attr_name: str, imported_modules: str) -> int: - """Whether a node is `t.attr_name` or a bare `attr_name` imported from t.""" + def _is_builtin_marker(self, node: ast.AST*, attr_name: str, imported_modules: str) -> int: + """Whether a node is the bare builtin marker name (e.g. CPtr / CRef).""" if node is None or attr_name is None: return 0 - if node.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(node) - if at.attr is None: return 0 - if string.strcmp(at.attr, attr_name) != 0: return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 - val_nm: ast.Name* = ast.Name*(at.value) - if val_nm.id is None: return 0 - if string.strcmp(val_nm.id, "t") == 0: - # t is a builtin library (SHA1-exempt) and may be absent from _imported_modules; - # an explicit t.CPtr / t.CVoid unambiguously means module t. - return 1 - return 0 - # Bare form: from t import attr_name -> Name(id == attr_name) - if node.kind() == ast.ASTKind.Name: - nm: ast.Name* = ast.Name*(node) - if nm.id is None: return 0 - if string.strcmp(nm.id, attr_name) != 0: return 0 - # A bare name requires module t to be imported (from t import X registers it) - if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") == 0: return 0 - return 1 - return 0 + if node.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(node) + if nm.id is None: return 0 + if string.strcmp(nm.id, attr_name) != 0: return 0 + return 1 def _is_cptr_marker(self, node: ast.AST*, imported_modules: str) -> int: """Whether a node is a CPtr pointer marker: 1=yes / 0=no.""" - if self._is_t_attr(node, "CPtr", imported_modules) != 0: return 1 + if self._is_builtin_marker(node, "CPtr", imported_modules) != 0: return 1 if node is not None and node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: return 1 return 0 def _is_ref_marker(self, node: ast.AST*, imported_modules: str) -> int: """Whether a node is a CRef/CTempRef value-reference marker: 1=yes / 0=no.""" - if self._is_t_attr(node, "CRef", imported_modules) != 0: return 1 - if self._is_t_attr(node, "CTempRef", imported_modules) != 0: return 1 + if self._is_builtin_marker(node, "CRef", imported_modules) != 0: return 1 + if self._is_builtin_marker(node, "CTempRef", imported_modules) != 0: return 1 return 0 def _is_byteorder_marker(self, node: ast.AST*, imported_modules: str) -> int: """Whether a node is a byte-order marker: 0=none / 1=BigEndian / 2=LittleEndian.""" - if self._is_t_attr(node, "BigEndian", imported_modules) != 0: return 1 - if self._is_t_attr(node, "LittleEndian", imported_modules) != 0: return 2 + if self._is_builtin_marker(node, "BigEndian", imported_modules) != 0: return 1 + if self._is_builtin_marker(node, "LittleEndian", imported_modules) != 0: return 2 return 0 def target_is_big_endian(self) -> int: """Whether the compilation target is big-endian (1) or little-endian (0). @@ -1511,12 +1509,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): """Syntactic value-reference marker test (no import context): 0=none / 1=CRef / 2=CTempRef.""" if node is None: return 0 nm: str = None - if node.kind() == ast.ASTKind.Attribute: - at: ast.Attribute* = ast.Attribute*(node) - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - at_vn: ast.Name* = ast.Name*(at.value) - if at_vn.id is not None and string.strcmp(at_vn.id, "t") == 0: nm = at.attr - elif node.kind() == ast.ASTKind.Name: + if node.kind() == ast.ASTKind.Name: nm = (ast.Name*(node)).id if nm is None: return 0 if string.strcmp(nm, "CRef") == 0: return 1 @@ -1527,10 +1520,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if node is None or node.kind() != ast.ASTKind.BinOp: return 0 bo: ast.BinOp* = ast.BinOp*(node) if bo.op != ast.OpKind.BitOr: return 0 - if self._is_t_attr(bo.left, "CTempRef", imported_modules) != 0: return 2 - if self._is_t_attr(bo.right, "CTempRef", imported_modules) != 0: return 2 - if self._is_t_attr(bo.left, "CRef", imported_modules) != 0: return 1 - if self._is_t_attr(bo.right, "CRef", imported_modules) != 0: return 1 + if self._is_builtin_marker(bo.left, "CTempRef", imported_modules) != 0: return 2 + if self._is_builtin_marker(bo.right, "CTempRef", imported_modules) != 0: return 2 + if self._is_builtin_marker(bo.left, "CRef", imported_modules) != 0: return 1 + if self._is_builtin_marker(bo.right, "CRef", imported_modules) != 0: return 1 return 0 def reject_ref_marker_position(self, node: ast.AST*, imported_modules: str, where: str) -> int: """Fail fast when a value-reference marker (&T / &temp T) is used outside a parameter position.""" @@ -1538,18 +1531,15 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenErr.fatal_error(node, f"value-reference parameter annotation '&T' / '&temp T' is only allowed in function parameter position, not for {where}", "TypeError") return 1 def _is_cptr_subscript(self, node: ast.AST*) -> int: - """Whether a node is a t.CPtr[T] subscript pointer type (e.g. t.CPtr[t.CPtr]).""" + """Whether a node is a CPtr[T] subscript pointer type (e.g. CPtr[CPtr]).""" 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.Attribute: return 0 - at: ast.Attribute* = ast.Attribute*(sub.value) - if at.attr is None or string.strcmp(at.attr, "CPtr") != 0: return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: return 0 - nm: ast.Name* = ast.Name*(at.value) - if nm.id is None or string.strcmp(nm.id, "t") != 0: return 0 + if sub.value is None or sub.value.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(sub.value) + if nm.id is None or string.strcmp(nm.id, "CPtr") != 0: return 0 return 1 - def _is_tattr_marker(self, node: ast.AST*) -> int: - """Whether a node is a `t.attr.` marker (including the call form).""" + def _is_cattr_marker(self, node: ast.AST*) -> int: + """Whether a node is an `attr.` builtin marker (including the call form).""" if node is None: return 0 inner: ast.AST* = node if inner.kind() == ast.ASTKind.Call: @@ -1559,22 +1549,17 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if inner.kind() != ast.ASTKind.Attribute: return 0 at: ast.Attribute* = ast.Attribute*(inner) if at.attr is None or at.value is None: return 0 - if at.value.kind() != ast.ASTKind.Attribute: return 0 - root: ast.Attribute* = ast.Attribute*(at.value) - if root.attr is None or root.value is None: return 0 - if root.value.kind() != ast.ASTKind.Name: return 0 - rn: ast.Name* = ast.Name*(root.value) - if rn.id is None or string.strcmp(rn.id, "t") != 0: return 0 - if string.strcmp(root.attr, "attr") != 0: return 0 + if at.value.kind() != ast.ASTKind.Name: return 0 + rn: ast.Name* = ast.Name*(at.value) + if rn.id is None or string.strcmp(rn.id, "attr") != 0: return 0 return 1 def _is_cvoid_marker(self, node: ast.AST*, imported_modules: str) -> int: """Whether a node is a CVoid pointer marker: 1=yes / 0=no.""" - if self._is_t_attr(node, "CVoid", imported_modules) != 0: return 1 + if self._is_builtin_marker(node, "CVoid", imported_modules) != 0: return 1 if node is not None and node.kind() == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) - # Bare CVoid (from t import CVoid) is synonymous with the builtin alias void - if nm.id is not None: - if string.strcmp(nm.id, "CVoid") == 0 or string.strcmp(nm.id, "void") == 0: return 1 + # Bare CVoid is synonymous with the builtin alias void + if nm.id is not None and string.strcmp(nm.id, "void") == 0: return 1 return 0 def annotation_to_str(self, annot: ast.AST*) -> str: """Render a type-annotation AST to a readable string; None means not extractable.""" @@ -1713,7 +1698,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # can record it; consumers degrade gracefully for non-struct names. if at.value is not None and at.value.kind() == ast.ASTKind.Name: val_nm2: ast.Name* = ast.Name*(at.value) - if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: return at.attr + if val_nm2.id is not None and string.strcmp(val_nm2.id, "attr") == 0: return at.attr # Restore import aliases: val_nm2.id may be an alias like Y for # "import X as Y"; storing the real qualified name enables cross-module lookup. real_mod2: str = val_nm2.id @@ -2069,11 +2054,11 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): elif string.strcmp(nm.id, "None") == 0: return mlirlite.Void(pool) elif string.strcmp(nm.id, "int") == 0: return mlirlite.Int32(pool) elif string.strcmp(nm.id, "char") == 0: - # char = i8 (consistent with CChar/char in map_t_type) + # char = i8 (consistent with CChar/char in map_builtin_type) return mlirlite.Int8(pool) elif string.strcmp(nm.id, "bytes") == 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) elif string.strcmp(nm.id, "bool") == 0: - # bool = t.CBool = i1 (consistent with CBool in map_t_type) + # bool = t.CBool = i1 (consistent with CBool in map_builtin_type) return mlirlite.Int1(pool) # Bare float types: float = t.CFloat = f32, double = t.CDouble = f64 elif string.strcmp(nm.id, "float") == 0: return mlirlite.Float(pool) @@ -2133,9 +2118,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType._ctypedef_pop_visiting() if inner_ty is not None: return inner_ty else: self.Gen.TypeGenCType._ctypedef_pop_visiting() - # Fallback: map_t_type hardcoded typedefs (VOIDPTR/HANDLE/ULONG etc.) resolve even + # Fallback: map_builtin_type hardcoded typedefs (VOIDPTR/HANDLE/ULONG etc.) resolve even # when from-import lookup fails; struct names return None and are deferred by declare_only. - mapped_ty_fallback: mlirlite.LLVMType* = self.map_t_type(pool, nm.id) + mapped_ty_fallback: mlirlite.LLVMType* = self.map_builtin_type(pool, nm.id) if mapped_ty_fallback is not None: return mapped_ty_fallback # [stage 1a] from-import alias reverse lookup: a bare alias XXX is in no table, so # reverse it to the original name and recurse (supports typedef alias chains). @@ -2190,38 +2175,34 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if k == ast.ASTKind.Attribute: at: ast.Attribute* = ast.Attribute*(node) if at.attr is None: return None - # Check whether value is Name('t') or Name('c') if at.value is not None and at.value.kind() == ast.ASTKind.Name: val_name: ast.Name* = ast.Name*(at.value) if val_name.id is not None: - # t/c are builtin libraries (SHA1-exempt); an explicit t.XXX unambiguously - # means the builtin module and does not rely on imported_modules. - is_builtin_attr: int = 0 - if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0: is_builtin_attr = 1 - if is_builtin_attr == 0: - # SHA1 prefix ("{16hex}.Class"): the module segment is a SHA1 (already - # compiled), so skip the imported_modules check via GenApi.is_sha1_hex16. - sha1_attr: int = GenApi.is_sha1_hex16(val_name.id) - if sha1_attr == 0: - mod_imp: int = self.Gen.ImportsGen.is_module_imported(imported_modules, val_name.id) - if mod_imp == 0: - # [builtins last match] Library-module typedef exemption: a typedef - # in a registered library module resolves without an explicit import. - td_known: int = 0 - # First restore the module name via the builtins import alias (__stdint -> stdint) - v_real: str = self._resolve_import_alias(val_name.id) - if v_real is None: v_real = val_name.id - if StubMergerStore.LookupSha1ByModName(v_real) is not None: - lib_td_v: str = self._lookup_library_typedef(pool, val_name.id, at.attr) - if lib_td_v is not None: td_known = 1 - if td_known == 0: - # Nested class/struct: `Outer.Inner` (base is a class name); a - # flat-name `Outer_Inner` lookup cannot shadow any existing success. - nested_ty_q: mlirlite.LLVMType* = self._resolve_nested_class_type(pool, val_name.id, at.attr, trans) - if nested_ty_q is not None: return nested_ty_q - return None + # `attr.` is a builtin attribute marker, never a type. + if string.strcmp(val_name.id, "attr") == 0: return None + # SHA1 prefix ("{16hex}.Class"): the module segment is a SHA1 (already + # compiled), so skip the imported_modules check via GenApi.is_sha1_hex16. + sha1_attr: int = GenApi.is_sha1_hex16(val_name.id) + if sha1_attr == 0: + mod_imp: int = self.Gen.ImportsGen.is_module_imported(imported_modules, val_name.id) + if mod_imp == 0: + # [builtins last match] Library-module typedef exemption: a typedef + # in a registered library module resolves without an explicit import. + td_known: int = 0 + # First restore the module name via the builtins import alias (__stdint -> stdint) + v_real: str = self._resolve_import_alias(val_name.id) + if v_real is None: v_real = val_name.id + if StubMergerStore.LookupSha1ByModName(v_real) is not None: + lib_td_v: str = self._lookup_library_typedef(pool, val_name.id, at.attr) + if lib_td_v is not None: td_known = 1 + if td_known == 0: + # Nested class/struct: `Outer.Inner` (base is a class name); a + # flat-name `Outer_Inner` lookup cannot shadow any existing success. + nested_ty_q: mlirlite.LLVMType* = self._resolve_nested_class_type(pool, val_name.id, at.attr, trans) + if nested_ty_q is not None: return nested_ty_q + return None # [stage 1b] Prefer the library typedef dynamic table (single source of - # truth); on miss fall back to map_t_type (t/c internal special cases). + # truth); on miss fall back to map_builtin_type (t/c internal special cases). if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH: ctypedef_attr: str = self.Gen.TypeGenCType.lookup_ctypedef(at.attr) if ctypedef_attr is not None and self.Gen.TypeGenCType.CTypedefFound != 0: @@ -2234,7 +2215,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType._ctypedef_pop_visiting() if inner_ty_attr is not None: return inner_ty_attr # First try the builtin type mapping (int etc.) - mapped_ty: mlirlite.LLVMType* = self.map_t_type(pool, at.attr) + mapped_ty: mlirlite.LLVMType* = self.map_builtin_type(pool, at.attr) if mapped_ty is not None: return mapped_ty # Module-qualified class type: Module.ClassName (namespace isolation). # The SHA1-prefixed form should use the full name to hit the defining struct. @@ -2244,14 +2225,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): mod_sha1_rv: str = None # val_name.id is the module segment: it is a SHA1 alias only if it is exactly # 16 lowercase hex (via GenApi.is_sha1_hex16, the single source of truth). - if is_builtin_attr == 0 and GenApi.is_sha1_hex16(val_name.id) != 0: + if GenApi.is_sha1_hex16(val_name.id) != 0: mod_sha1_rv = val_name.id full_q: str = self._concat_sha1_class(pool, val_name.id, at.attr) if full_q is not None: full_attr_ty = self.Gen.StructGen.get_struct_type(full_q) if full_attr_ty is not None: return full_attr_ty # Cross-module qualified name (Module.Class): resolve by module ownership, not # bare-name fallback; module name -> sha1 then hit "{sha1}.{Class}" exactly. - if is_builtin_attr == 0: + if val_name.id is not None: # Module name -> sha1 (exact/suffix/alias restoration via # StructGenMixin._resolve_module_sha1). mod_sha1_v: str = self.Gen.StructGen._resolve_module_sha1(val_name.id, from_imports) @@ -2325,7 +2306,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Nested module-qualified enum class (three-level name): look up the enum base type if self.Gen.StmtGenDecl.is_enum_class(at.attr) == 1: return self.Gen.StmtGenDecl.get_enum_base_type(at.attr) # Nested module-qualified typedef (win32.win32base.HANDLE = VOIDPTR): same - # lookup_ctypedef + recursion + map_t_type fallback as the Name branch. + # lookup_ctypedef + recursion + map_builtin_type fallback as the Name branch. if self.Gen.TypeGenCType.CTypedefResolveDepth < TypeGenMixin.MAX_CTYPEDEF_DEPTH: nested_td_str: str = self.Gen.TypeGenCType.lookup_ctypedef(at.attr) if nested_td_str is not None and self.Gen.TypeGenCType.CTypedefFound != 0: @@ -2338,7 +2319,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): self.Gen.TypeGenCType._ctypedef_pop_visiting() if nested_ty is not None: return nested_ty else: self.Gen.TypeGenCType._ctypedef_pop_visiting() - mapped_ty_na: mlirlite.LLVMType* = self.map_t_type(pool, at.attr) + mapped_ty_na: mlirlite.LLVMType* = self.map_builtin_type(pool, at.attr) if mapped_ty_na is not None: return mapped_ty_na # Nested module-qualified typedef fallback (win32.win32base.HANDLE = VOIDPTR): # build the full module path from the nested Attribute, then scan the library source. @@ -2382,24 +2363,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # (left marker -> other is right; right marker -> other is left). other_node: ast.AST* = bop.left if left_is_cptr != 0 or left_is_ref != 0: other_node = bop.right - # Detect whether the other side is t.CVoid (void* = i8*), strictly validating - # the full form (Attribute with value Name("t"), or bare CVoid with t imported). - other_is_cvoid: int = 0 - if other_node is not None: - if other_node.kind() == ast.ASTKind.Attribute: - oat2: ast.Attribute* = ast.Attribute*(other_node) - if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0: - if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name: - ov2: ast.Name* = ast.Name*(oat2.value) - if ov2.id is not None and string.strcmp(ov2.id, "t") == 0: other_is_cvoid = 1 - elif other_node.kind() == ast.ASTKind.Name: - onm2: ast.Name* = ast.Name*(other_node) - if onm2.id is not None: - if string.strcmp(onm2.id, "CVoid") == 0: - if self.Gen.ImportsGen.is_module_imported(imported_modules, "t") != 0: other_is_cvoid = 1 - elif string.strcmp(onm2.id, "void") == 0: - # Builtin alias void: synonymous with t.CVoid, no import t needed - other_is_cvoid = 1 + # Detect whether the other side is CVoid / void (void* = i8*). + other_is_cvoid: int = self._is_cvoid_marker(other_node, imported_modules) if other_is_cvoid != 0: return mlirlite.Ptr(pool, mlirlite.Int8(pool)) other_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, other_node, imported_modules, from_imports, trans, depth + 1) # If the result is void, merging with CPtr gives void* = i8*; must guard None @@ -2508,10 +2473,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # No CPtr marker: return the first non-attribute-marker side. Attribute markers # (t.attr.) are not types and are prepended left, so skip them. - if self._is_tattr_marker(bop.left) == 0: + if self._is_cattr_marker(bop.left) == 0: left_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.left, imported_modules, from_imports, trans, depth + 1) if left_ty is not None: return left_ty - if self._is_tattr_marker(bop.right) == 0: + if self._is_cattr_marker(bop.right) == 0: right_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, bop.right, imported_modules, from_imports, trans, depth + 1) if right_ty is not None: return right_ty return None @@ -2575,9 +2540,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): count_n: int = self.Gen.TypeGenCType._eval_const_int_expr(count_node_n, pool, from_imports, imported_modules) if self.Gen.TypeGenCType.ConstEvalOk == 0 or count_n <= 0: return None return mlirlite.Array(pool, elem_ty_n, count_n) - # rawptr[T] builtin bare pointer: equivalent to t.CPtr[T] -> Ptr(T), always - # appending exactly 1 layer. The old "absorb a layer" compensation is removed. - if string.strcmp(gen_nm.id, "rawptr") == 0: + # rawptr[T] / CPtr[T] builtin bare pointer: equivalent to `T*` -> Ptr(T), + # always appending exactly 1 layer. The old "absorb a layer" compensation is removed. + if string.strcmp(gen_nm.id, "rawptr") == 0 or string.strcmp(gen_nm.id, "CPtr") == 0: if sub.slice.kind() != ast.ASTKind.Tuple: rp_elem: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) if rp_elem is None: return None @@ -2607,30 +2572,26 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): fb_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, fb_node, imported_modules, from_imports, trans, depth + 1) if fb_ty is not None: return fb_ty return None - # Check whether value is an Attribute (t.CArray / t.Callable / module-qualified generic like numpy.ndarray[T]) - if sub.value.kind() != ast.ASTKind.Attribute: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only t.CArray / t.Callable are supported)") + # Check whether value is an Attribute (module-qualified generic like numpy.ndarray[T]) + if sub.value.kind() != ast.ASTKind.Attribute: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only CArray / Callable are supported)") arr_at: ast.Attribute* = ast.Attribute*(sub.value) if arr_at.attr is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript Attribute missing attr") - # Module-qualified generic class: numpy.ndarray[t.CDouble] -> use the bare class name - # ndarray for specialization (before the t.CArray / t.Callable checks). + # Module-qualified generic class: numpy.ndarray[CDouble] -> use the bare class name + # ndarray for specialization. if trans is not None: if self.Gen.ClassGenGeneric._find_generic_template(arr_at.attr) is not None: return self._resolve_generic_subscript_ty(pool, sub, arr_at.attr, trans, imported_modules, from_imports, depth + 1) - if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray / t.Callable must be qualified by the module name") + if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: self.Gen.TypeGenErr.fatal_type_error(node, "CArray / Callable must be qualified by the module name") arr_val_name: ast.Name* = ast.Name*(arr_at.value) if arr_val_name.id is None: self.Gen.TypeGenErr.fatal_type_error(node, "Subscript module name is None") - # Function pointer type: t.Callable[[A, B], Ret] -> i8* (function values are bitcast to + # Function pointer type: Callable[[A, B], Ret] -> i8* (function values are bitcast to # i8* for storage and the signature is rebuilt at calls, matching VPC convention). if string.strcmp(arr_at.attr, "Callable") == 0: - # t/c are builtin namespaces (not compiled, not in imported_modules); no import check needed - if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.Callable module not imported") return mlirlite.Ptr(pool, mlirlite.Int8(pool)) - # Pointer type: t.CPtr[T] -> Ptr(T); always appends exactly 1 layer, no exceptions - # (`t.CPtr[T]` == `T*`). The old "absorb a layer" compensation is removed. + # Pointer type: CPtr[T] -> Ptr(T); always appends exactly 1 layer, no exceptions. if string.strcmp(arr_at.attr, "CPtr") == 0: - if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.CPtr module not imported") + if self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: + self.Gen.TypeGenErr.fatal_type_error(node, "CPtr module not imported") inner_cptr_ty: mlirlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) if inner_cptr_ty is None: # Element type not ready (class not yet registered): prefer a forward declaration @@ -2639,9 +2600,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if _fwd_cptr_ty is not None: return _fwd_cptr_ty return None return mlirlite.Ptr(pool, inner_cptr_ty) - if string.strcmp(arr_at.attr, "CArray") != 0: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only t.CArray / t.Callable are supported)") - if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: - self.Gen.TypeGenErr.fatal_type_error(node, "t.CArray module not imported") + if string.strcmp(arr_at.attr, "CArray") != 0: self.Gen.TypeGenErr.fatal_type_error(node, "Unsupported Subscript type annotation (only CArray / Callable are supported)") + if self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: + self.Gen.TypeGenErr.fatal_type_error(node, "CArray module not imported") # Single-arg form: t.CArray[elem_ty] -> Ptr(elem_ty), equivalent to # t.CArray[elem_ty, None] (statically inferred length array). if sub.slice.kind() != ast.ASTKind.Tuple: diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index 5de4d88..0e5adaa 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -86,6 +86,44 @@ def SpecSignFromTypeNameSpan(text: str, start: sizet, end: sizet) -> int: 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 + if _spec_name_eq(text, start, end, "uint8") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uint16") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uint32") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uint64") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintfast8") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintfast16") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintfast32") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintfast64") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintleast8") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintleast16") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintleast32") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintleast64") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uchar") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "ushort") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uint") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "ulong") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "ulonglong") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "uintptr") != 0: return TS_SIGN_UNSIGNED + if _spec_name_eq(text, start, end, "int8") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "int16") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "int32") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "int64") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intfast8") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intfast16") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intfast32") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intfast64") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intleast8") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intleast16") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intleast32") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "intleast64") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "short") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "long") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "longlong") != 0: return TS_SIGN_SIGNED + if _spec_name_eq(text, start, end, "ptrdifft") != 0: return TS_SIGN_SIGNED + 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 ---