feat(tpv): 新增 TypeSpec 统一类型描述符(S1,未接线)
类型信息目前散落在 AnnotClassName/IsPtrElement/TypeStr 等字符串与布尔里, 导致「无符号/指针层级/数组维度/函数签名」到处重复解析且结论不一致 (Debugger/_Type.md 二次盘点 A/C 类)。 新增 App/lib/core/Gen/Type/TypeSpec.vp 作为统一描述符: - TypeSpec:Kind/Bits/IsSigned/PtrLevel/Elem/ArrayCount/BaseName/Ret/Params/ ParamCount/IsVarArg/Storage,以及元素语义三元组 ElemBits/IsElemPtr/ DerefBase(替代单一 IsPtrElement 布尔——同一 Ptr(i8) 下存在两种相反语义) - TypeSpecArena 驻留表(对象持有,非全局表)+ InternSpec 去重(键=规范文本) - SpecToText/TextToSpec 规范文本编解码(驻留键/日志/vpi 通道) - 构造器 NewTypeSpec/NewTypeStruct/NewTypePtr/NewTypeArray/NewTypeFunc - 访问器 SpecIsPtr/SpecPointedTo/SpecIsUnsigned/SpecBitWidth - SpecSelfCheck 自检(不参与编译流程) - 实例与数组一律 PermPool 分配(跨 mark 持久,跨模块可直接传指针) GenTypes 仅加 import 使该模块参与编译(否则新文件不会被编译、无法验证); 未改动任何既有调用点,产物 IR 应与上一版一致。
This commit is contained in:
1 parent
b8470c1cae
commit
b1090abe70
2 files changed
+773
No files matched your search
@@ -3,6 +3,10 @@ from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
# TypeSpec:统一类型描述符(Debugger/_Type.md 第 6 节设计)。
|
||||
# S1 阶段仅 import 使该模块参与编译(尚未在任何条目上使用其字段);
|
||||
# S2 起在 VarEntry/FieldEntry/FuncEntry 上加 Spec 字段并双写。
|
||||
import lib.core.Gen.Type.TypeSpec as TypeSpec
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -0,0 +1,769 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeSpec - 统一类型描述符(对齐 TPC lib/core/TypeSpec.py,去 Python 化)
|
||||
#
|
||||
# 背景(见 Debugger/_Type.md 第 6 节设计):
|
||||
# TPV 现有类型信息散落在「字符串 + 零散布尔」里 —— VarEntry.AnnotClassName /
|
||||
# FieldEntry.AnnotClassName(注解类名串当影子类型系统)、VarEntry.IsPtrElement
|
||||
# (单一布尔,只覆盖一种 8 字节步长情形)、FuncEntry.TypeStr(函数类型存文本),
|
||||
# 而 llvmlite.LLVMType 只保留解析结果、已抹平指针层级/数组维度/原始注解。
|
||||
# 结果是「是否无符号/指针几层/数组几维/函数签名」到处重复解析字符串
|
||||
# (同一值被末段类名/完整限定名/精确名/mangled 前缀/截断串五种语义解释)。
|
||||
#
|
||||
# 本文件是 S1 阶段产物:**只提供结构与构造/序列化,不改动任何既有调用点**。
|
||||
# S2 起才在各解析处「双写」本结构;S3 逐块切读;S4 删旧字符串路径。
|
||||
#
|
||||
# 生命周期(设计 D1):实例与内部数组一律 `CompilerFactory.factory.PermPool`
|
||||
# 分配(契约见 CompilerFactory.vp:跨 mark 持久、从不 reset),故跨文件/跨模块
|
||||
# 可直接传指针,无需序列化。代价是 PermPool 只增不减 ⇒ 由 InternSpec 驻留去重。
|
||||
#
|
||||
# 不用全局表:驻留表挂在 TypeSpecArena 实例上,由调用方(S2 起为 Generator)
|
||||
# 持有并传入,避免模块级可变态。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Kind - 基础类型种类
|
||||
# ============================================================
|
||||
TS_UNKNOWN: t.CDefine = 0
|
||||
TS_INT: t.CDefine = 1
|
||||
TS_UINT: t.CDefine = 2
|
||||
TS_FLOAT: t.CDefine = 3
|
||||
TS_BOOL: t.CDefine = 4
|
||||
TS_PTR: t.CDefine = 5
|
||||
TS_ARRAY: t.CDefine = 6
|
||||
TS_STRUCT: t.CDefine = 7
|
||||
TS_VOID: t.CDefine = 8
|
||||
TS_FUNC: t.CDefine = 9
|
||||
TS_UNION: t.CDefine = 10
|
||||
TS_ENUM: t.CDefine = 11
|
||||
|
||||
# ============================================================
|
||||
# IsSigned - 符号性(单一真源,替代 _annot_str_unsigned 的子串扫描)
|
||||
# ============================================================
|
||||
TS_SIGN_UNKNOWN: t.CDefine = -1
|
||||
TS_SIGN_UNSIGNED: t.CDefine = 0
|
||||
TS_SIGN_SIGNED: t.CDefine = 1
|
||||
|
||||
# 驻留表默认容量与单条类型文本上限(超限 fail-fast,绝不静默丢弃/截断)
|
||||
# 容量 × 文本上限即驻留表键缓冲的 PermPool 占用(8192 × 256 = 2MB)
|
||||
SPEC_INTERN_MAX: t.CDefine = 8192
|
||||
SPEC_TEXT_MAX: t.CDefine = 256
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeSpec - 类型描述符
|
||||
#
|
||||
# 元素语义三字段说明(ElemBits/IsElemPtr/DerefBase):
|
||||
# 它们替代旧的 VarEntry.IsPtrElement 单一布尔。原因(_Type.md D7-4):
|
||||
# `str | t.CPtr`、`bytes | t.CPtr`、泛型 `T | t.CPtr`、`64 位标量 | t.CPtr`
|
||||
# 退化后的 LLVM 类型**都是单层 Ptr(i8)**,即 PtrLevel=1 同时对应两种相反语义,
|
||||
# 仅靠指针层级无法区分;区分靠的是注解内容 ⇒ 需要「元素宽度 + 元素是否指针 +
|
||||
# 基址是否需二次解引用」三元组。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeSpec:
|
||||
"""统一类型描述符(字段语义见上)"""
|
||||
Kind: int # TS_* 之一
|
||||
Bits: int # 位宽;非整型/浮点为 0
|
||||
IsSigned: int # TS_SIGN_* (-1 未知 / 0 无符号 / 1 有符号)
|
||||
PtrLevel: int # 指针层级(0=非指针)
|
||||
Elem: TypeSpec | t.CPtr # Ptr/Array 的指向或元素(None=无)
|
||||
ArrayCount: int # Array 的元素个数(0=未知/动态)
|
||||
BaseName: str # 结构体/枚举/类名(带模块 sha1;PermPool 深拷贝)
|
||||
Ret: TypeSpec | t.CPtr # Func:返回类型
|
||||
Params: sizet | t.CPtr # Func:参数数组(连续 TypeSpec* 指针,ParamCount 个)
|
||||
ParamCount: int # Func:参数个数
|
||||
IsVarArg: int # Func:1=变参(...)
|
||||
Storage: int # 限定宏位标志(0=无)
|
||||
ElemBits: int # 元素槽位宽(元素语义三元组 1/3)
|
||||
IsElemPtr: int # 元素是否为指针(1=是)(2/3)
|
||||
DerefBase: int # 基址是否需二次解引用(1=是)(3/3)
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 解析结果缓存(可空)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeSpecArena - 驻留表(对象持有,非全局表)
|
||||
#
|
||||
# Keys :cap * SPEC_TEXT_MAX 的连续文本缓冲,第 i 条键位于 Keys + i*SPEC_TEXT_MAX
|
||||
# Specs :cap 个 TypeSpec 指针
|
||||
# Count :已驻留条数;Cap:容量
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeSpecArena:
|
||||
"""TypeSpec 驻留表(按规范文本键去重,同型只存一份)"""
|
||||
Keys: bytes
|
||||
Specs: sizet | t.CPtr
|
||||
Count: int
|
||||
Cap: int
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_key_at - 取第 i 个键的 str 指针(键缓冲内偏移 i * SPEC_TEXT_MAX)
|
||||
# ============================================================
|
||||
def _spec_key_at(keys: bytes, index: int) -> str:
|
||||
"""返回第 index 条键的 str 指针(指向 keys 缓冲内部,不可 free)"""
|
||||
if keys is None or index < 0:
|
||||
return None
|
||||
addr: uint64 = uint64(keys) + uint64(index * SPEC_TEXT_MAX)
|
||||
return (str | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SpecArenaInit - 初始化驻留表(幂等;cap<=0 时用 SPEC_INTERN_MAX)
|
||||
# 返回 0=成功 / 1=失败(分配失败 fail-fast 由调用方处理,此处返回错误码)
|
||||
# ============================================================
|
||||
def SpecArenaInit(arena: TypeSpecArena | t.CPtr, cap: int) -> int:
|
||||
"""初始化驻留表;已初始化则直接返回 0"""
|
||||
if arena is None:
|
||||
return 1
|
||||
if arena.Keys is not None:
|
||||
return 0
|
||||
use_cap: int = cap
|
||||
if use_cap <= 0:
|
||||
use_cap = SPEC_INTERN_MAX
|
||||
pp: memhub.MemBuddy | t.CPtr = CompilerFactory.factory.PermPool
|
||||
keys: bytes = pp.alloc(use_cap * SPEC_TEXT_MAX)
|
||||
if keys is None:
|
||||
return 1
|
||||
specs: sizet | t.CPtr = pp.alloc(use_cap * 8)
|
||||
if specs is None:
|
||||
return 1
|
||||
string.memset(keys, 0, use_cap * SPEC_TEXT_MAX)
|
||||
string.memset(specs, 0, use_cap * 8)
|
||||
arena.Keys = keys
|
||||
arena.Specs = specs
|
||||
arena.Count = 0
|
||||
arena.Cap = use_cap
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_alloc - 从 PermPool 分配一个清零的 TypeSpec(不驻留,内部用)
|
||||
# ============================================================
|
||||
def _spec_alloc() -> TypeSpec | t.CPtr:
|
||||
"""分配并清零一个 TypeSpec(PermPool)"""
|
||||
pp: memhub.MemBuddy | t.CPtr = CompilerFactory.factory.PermPool
|
||||
size: sizet = TypeSpec.__sizeof__()
|
||||
sp: TypeSpec | t.CPtr = (TypeSpec | t.CPtr)(t.CVoid(pp.alloc(size), t.CPtr))
|
||||
if sp is None:
|
||||
return None
|
||||
string.memset(sp, 0, size)
|
||||
sp.Kind = TS_UNKNOWN
|
||||
sp.Bits = 0
|
||||
sp.IsSigned = TS_SIGN_UNKNOWN
|
||||
sp.PtrLevel = 0
|
||||
sp.IsVarArg = 0
|
||||
sp.Storage = 0
|
||||
return sp
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_make - 构造一个基础 TypeSpec(不驻留)
|
||||
# ============================================================
|
||||
def _spec_make(kind: int, bits: int, is_signed: int) -> TypeSpec | t.CPtr:
|
||||
"""构造基础 TypeSpec(PermPool,不驻留)"""
|
||||
sp: TypeSpec | t.CPtr = _spec_alloc()
|
||||
if sp is None:
|
||||
return None
|
||||
sp.Kind = kind
|
||||
sp.Bits = bits
|
||||
sp.IsSigned = is_signed
|
||||
return sp
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_set_struct_name - 深拷贝类名到 PermPool(跨文件存活)
|
||||
# ============================================================
|
||||
def _spec_set_struct_name(sp: TypeSpec | t.CPtr, name: str) -> int:
|
||||
"""把类名深拷贝到 PermPool 并写入 BaseName,返回 0=成功 / 1=失败"""
|
||||
if sp is None or name is None:
|
||||
return 1
|
||||
n: sizet = string.strlen(name)
|
||||
if n <= 0:
|
||||
return 1
|
||||
buf: str = CompilerFactory.factory.PermPool.alloc(n + 1)
|
||||
if buf is None:
|
||||
return 1
|
||||
string.strcpy(buf, name)
|
||||
sp.BaseName = buf
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeSpec - 构造基础类型(驻留)
|
||||
# ============================================================
|
||||
def NewTypeSpec(arena: TypeSpecArena | t.CPtr, kind: int,
|
||||
bits: int, is_signed: int) -> TypeSpec | t.CPtr:
|
||||
"""构造基础 TypeSpec 并驻留,失败返回 None"""
|
||||
sp: TypeSpec | t.CPtr = _spec_make(kind, bits, is_signed)
|
||||
if sp is None:
|
||||
return None
|
||||
return InternSpec(arena, sp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeStruct - 构造结构体/枚举/类类型(驻留)
|
||||
# ============================================================
|
||||
def NewTypeStruct(arena: TypeSpecArena | t.CPtr, kind: int,
|
||||
base_name: str) -> TypeSpec | t.CPtr:
|
||||
"""构造 struct/union/enum 类型(BaseName 深拷贝 + 驻留),失败返回 None"""
|
||||
sp: TypeSpec | t.CPtr = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
|
||||
if sp is None:
|
||||
return None
|
||||
if _spec_set_struct_name(sp, base_name) != 0:
|
||||
return None
|
||||
return InternSpec(arena, sp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypePtr - 构造指针类型(PtrLevel = 元素 PtrLevel + 1,驻留)
|
||||
# ============================================================
|
||||
def NewTypePtr(arena: TypeSpecArena | t.CPtr,
|
||||
elem: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
|
||||
"""构造指针类型:指向 elem(PtrLevel 逐层递增),失败返回 None"""
|
||||
if elem is None:
|
||||
return None
|
||||
sp: TypeSpec | t.CPtr = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
|
||||
if sp is None:
|
||||
return None
|
||||
sp.Elem = elem
|
||||
sp.PtrLevel = elem.PtrLevel + 1
|
||||
sp.ElemBits = elem.Bits
|
||||
sp.IsElemPtr = 0
|
||||
if elem.Kind == TS_PTR:
|
||||
sp.IsElemPtr = 1
|
||||
return InternSpec(arena, sp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeArray - 构造数组类型(ArrayCount 个 elem,驻留)
|
||||
# ============================================================
|
||||
def NewTypeArray(arena: TypeSpecArena | t.CPtr, elem: TypeSpec | t.CPtr,
|
||||
count: int) -> TypeSpec | t.CPtr:
|
||||
"""构造数组类型:elem[count](count<=0 表示长度未知/动态),失败返回 None"""
|
||||
if elem is None or count < 0:
|
||||
return None
|
||||
sp: TypeSpec | t.CPtr = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
|
||||
if sp is None:
|
||||
return None
|
||||
sp.Elem = elem
|
||||
sp.ArrayCount = count
|
||||
sp.ElemBits = elem.Bits
|
||||
sp.IsElemPtr = 0
|
||||
if elem.Kind == TS_PTR:
|
||||
sp.IsElemPtr = 1
|
||||
return InternSpec(arena, sp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeFunc - 构造函数签名类型(ret + 参数数组 + 变参,驻留)
|
||||
# params:TypeSpec* 连续数组(由调用方预先构造并保证存活);count 个
|
||||
# ============================================================
|
||||
def NewTypeFunc(arena: TypeSpecArena | t.CPtr, ret: TypeSpec | t.CPtr,
|
||||
params: sizet | t.CPtr, count: int,
|
||||
is_vararg: int) -> TypeSpec | t.CPtr:
|
||||
"""构造函数签名类型,失败返回 None"""
|
||||
if ret is None or count < 0:
|
||||
return None
|
||||
if count > 0 and params is None:
|
||||
return None
|
||||
sp: TypeSpec | t.CPtr = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
|
||||
if sp is None:
|
||||
return None
|
||||
sp.Ret = ret
|
||||
sp.Params = params
|
||||
sp.ParamCount = count
|
||||
sp.IsVarArg = is_vararg
|
||||
return InternSpec(arena, sp)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SpecBaseText - 基础类型(非 Ptr/Array/Func)的规范文本
|
||||
# 返回 0=已写入 / 1=不适用/失败
|
||||
# ============================================================
|
||||
def SpecBaseText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
|
||||
"""把基础类型写成规范文本;Ptr/Array/Func 不适用时返回 1"""
|
||||
if sp is None or buf is None or buf_size == 0:
|
||||
return 1
|
||||
if sp.Kind == TS_INT:
|
||||
viperlib.snprintf(buf, buf_size, "i%d", sp.Bits)
|
||||
return 0
|
||||
if sp.Kind == TS_UINT:
|
||||
viperlib.snprintf(buf, buf_size, "u%d", sp.Bits)
|
||||
return 0
|
||||
if sp.Kind == TS_FLOAT:
|
||||
viperlib.snprintf(buf, buf_size, "f%d", sp.Bits)
|
||||
return 0
|
||||
if sp.Kind == TS_BOOL:
|
||||
viperlib.snprintf(buf, buf_size, "bool")
|
||||
return 0
|
||||
if sp.Kind == TS_STRUCT:
|
||||
viperlib.snprintf(buf, buf_size, "st:%s", sp.BaseName)
|
||||
return 0
|
||||
if sp.Kind == TS_UNION:
|
||||
viperlib.snprintf(buf, buf_size, "un:%s", sp.BaseName)
|
||||
return 0
|
||||
if sp.Kind == TS_ENUM:
|
||||
viperlib.snprintf(buf, buf_size, "en:%s", sp.BaseName)
|
||||
return 0
|
||||
if sp.Kind == TS_VOID:
|
||||
viperlib.snprintf(buf, buf_size, "void")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SpecToText - 规范文本编码(驻留键 / 日志 / vpi·stub 通道)
|
||||
#
|
||||
# 格式草案:
|
||||
# i32 / u64 / f64 / bool / void
|
||||
# st:{sha1}.Class 结构体(BaseName 原样);un: / en: 同构,分别表示联合/枚举
|
||||
# p:INNER 指针(每层一个 "p:" 前缀,层数即 PtrLevel)
|
||||
# arr[N]:INNER 数组(N=0 表示长度未知)
|
||||
# fn(INNER,INNER,...)->RET 函数签名(变参追加 "...")
|
||||
# 递归深度上限 32(防环);超限或缓冲不足返回 1(fail-fast 由调用方决定)
|
||||
# ============================================================
|
||||
def SpecToText(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet) -> int:
|
||||
"""把 TypeSpec 编码为规范文本,返回 0=成功 / 1=失败"""
|
||||
return _spec_to_text(sp, buf, buf_size, 0)
|
||||
|
||||
|
||||
def _spec_to_text(sp: TypeSpec | t.CPtr, buf: str, buf_size: sizet,
|
||||
depth: int) -> int:
|
||||
"""SpecToText 的递归实现(depth 上限 32)"""
|
||||
if sp is None or buf is None or buf_size == 0 or depth > 32:
|
||||
return 1
|
||||
buf[0] = '\0'
|
||||
if sp.Kind == TS_PTR:
|
||||
# p: + 内层
|
||||
inner_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if inner_buf is None:
|
||||
return 1
|
||||
if _spec_to_text(sp.Elem, inner_buf, SPEC_TEXT_MAX, depth + 1) != 0:
|
||||
return 1
|
||||
viperlib.snprintf(buf, buf_size, "p:%s", inner_buf)
|
||||
return 0
|
||||
if sp.Kind == TS_ARRAY:
|
||||
# arr[N]: + 内层
|
||||
inner_buf_a: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if inner_buf_a is None:
|
||||
return 1
|
||||
if _spec_to_text(sp.Elem, inner_buf_a, SPEC_TEXT_MAX, depth + 1) != 0:
|
||||
return 1
|
||||
viperlib.snprintf(buf, buf_size, "arr[%d]:%s", sp.ArrayCount, inner_buf_a)
|
||||
return 0
|
||||
if sp.Kind == TS_FUNC:
|
||||
# fn(p1,p2,...)->ret
|
||||
pos: sizet = 0
|
||||
pos = _spec_text_append(buf, buf_size, pos, "fn(")
|
||||
i: int = 0
|
||||
while i < sp.ParamCount:
|
||||
if i > 0:
|
||||
pos = _spec_text_append(buf, buf_size, pos, ",")
|
||||
param: TypeSpec | t.CPtr = _spec_param_at(sp, i)
|
||||
if param is None:
|
||||
return 1
|
||||
param_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if param_buf is None:
|
||||
return 1
|
||||
if _spec_to_text(param, param_buf, SPEC_TEXT_MAX, depth + 1) != 0:
|
||||
return 1
|
||||
pos = _spec_text_append(buf, buf_size, pos, param_buf)
|
||||
i += 1
|
||||
if sp.IsVarArg == 1:
|
||||
if sp.ParamCount > 0:
|
||||
pos = _spec_text_append(buf, buf_size, pos, ",...")
|
||||
else:
|
||||
pos = _spec_text_append(buf, buf_size, pos, "...")
|
||||
pos = _spec_text_append(buf, buf_size, pos, ")->")
|
||||
ret_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if ret_buf is None:
|
||||
return 1
|
||||
if _spec_to_text(sp.Ret, ret_buf, SPEC_TEXT_MAX, depth + 1) != 0:
|
||||
return 1
|
||||
pos = _spec_text_append(buf, buf_size, pos, ret_buf)
|
||||
return 0
|
||||
# 基础类型
|
||||
return SpecBaseText(sp, buf, buf_size)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_text_append - 有界尾部追加(返回新的写入位置;溢出时不再写入)
|
||||
# ============================================================
|
||||
def _spec_text_append(buf: str, buf_size: sizet, pos: sizet, text: str) -> sizet:
|
||||
"""把 text 追加到 buf 的 pos 处(有界),返回新位置"""
|
||||
if buf is None or text is None:
|
||||
return pos
|
||||
tlen: sizet = string.strlen(text)
|
||||
i: sizet = 0
|
||||
while i < tlen:
|
||||
if pos + 1 >= buf_size:
|
||||
return pos
|
||||
buf[pos] = text[i]
|
||||
pos += 1
|
||||
i += 1
|
||||
buf[pos] = '\0'
|
||||
return pos
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_param_at - 取函数签名第 i 个参数 TypeSpec 指针
|
||||
# ============================================================
|
||||
def _spec_param_at(sp: TypeSpec | t.CPtr, index: int) -> TypeSpec | t.CPtr:
|
||||
"""返回 Func 类型第 index 个参数的 TypeSpec 指针,越界返回 None"""
|
||||
if sp is None or sp.Params is None or index < 0 or index >= sp.ParamCount:
|
||||
return None
|
||||
addr: uint64 = uint64(sp.Params) + uint64(index * 8)
|
||||
slot: sizet | t.CPtr = (sizet | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
if slot is None:
|
||||
return None
|
||||
return (TypeSpec | t.CPtr)(t.CVoid(uint64(slot[0]), t.CPtr))
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TextToSpec - 规范文本解码(SpecToText 的逆;不驻留,由调用方决定是否驻留)
|
||||
# 解析失败返回 None(fail-fast 由调用方决定)
|
||||
# ============================================================
|
||||
def TextToSpec(text: str) -> TypeSpec | t.CPtr:
|
||||
"""把规范文本解码为 TypeSpec(PermPool,不驻留),失败返回 None"""
|
||||
if text is None:
|
||||
return None
|
||||
return _text_to_spec(text, 0)
|
||||
|
||||
|
||||
def _text_to_spec(text: str, depth: int) -> TypeSpec | t.CPtr:
|
||||
"""TextToSpec 的递归实现(depth 上限 32)"""
|
||||
if text is None or depth > 32:
|
||||
return None
|
||||
# 指针:p:INNER
|
||||
if string.strncmp(text, "p:", 2) == 0:
|
||||
inner: TypeSpec | t.CPtr = _text_to_spec(text + 2, depth + 1)
|
||||
if inner is None:
|
||||
return None
|
||||
sp_p: TypeSpec | t.CPtr = _spec_make(TS_PTR, 0, TS_SIGN_UNKNOWN)
|
||||
if sp_p is None:
|
||||
return None
|
||||
sp_p.Elem = inner
|
||||
sp_p.PtrLevel = inner.PtrLevel + 1
|
||||
sp_p.ElemBits = inner.Bits
|
||||
if inner.Kind == TS_PTR:
|
||||
sp_p.IsElemPtr = 1
|
||||
return sp_p
|
||||
# 数组:arr[N]:INNER
|
||||
if string.strncmp(text, "arr[", 4) == 0:
|
||||
rb: str = string.strchr(text, ']')
|
||||
if rb is None:
|
||||
return None
|
||||
count: int = string.atoi(text + 4)
|
||||
if count < 0:
|
||||
return None
|
||||
colon: str = string.strchr(rb, ':')
|
||||
if colon is None:
|
||||
return None
|
||||
inner_a: TypeSpec | t.CPtr = _text_to_spec(colon + 1, depth + 1)
|
||||
if inner_a is None:
|
||||
return None
|
||||
sp_a: TypeSpec | t.CPtr = _spec_make(TS_ARRAY, 0, TS_SIGN_UNKNOWN)
|
||||
if sp_a is None:
|
||||
return None
|
||||
sp_a.Elem = inner_a
|
||||
sp_a.ArrayCount = count
|
||||
sp_a.ElemBits = inner_a.Bits
|
||||
if inner_a.Kind == TS_PTR:
|
||||
sp_a.IsElemPtr = 1
|
||||
return sp_a
|
||||
# 函数:fn(...)->RET
|
||||
if string.strncmp(text, "fn(", 3) == 0:
|
||||
return _text_to_func(text, depth)
|
||||
# 结构体/联合/枚举:st:NAME / un:NAME / en:NAME
|
||||
if string.strncmp(text, "st:", 3) == 0:
|
||||
return _spec_make_struct(TS_STRUCT, text + 3)
|
||||
if string.strncmp(text, "un:", 3) == 0:
|
||||
return _spec_make_struct(TS_UNION, text + 3)
|
||||
if string.strncmp(text, "en:", 3) == 0:
|
||||
return _spec_make_struct(TS_ENUM, text + 3)
|
||||
if string.strcmp(text, "bool") == 0:
|
||||
return _spec_make(TS_BOOL, 1, TS_SIGN_UNSIGNED)
|
||||
if string.strcmp(text, "void") == 0:
|
||||
return _spec_make(TS_VOID, 0, TS_SIGN_UNKNOWN)
|
||||
# i32 / u64 / f64
|
||||
if text[0] == 'u' or text[0] == 'i' or text[0] == 'f':
|
||||
bits: int = stdlib.atoi(text + 1)
|
||||
if bits <= 0:
|
||||
return None
|
||||
if text[0] == 'u':
|
||||
return _spec_make(TS_UINT, bits, TS_SIGN_UNSIGNED)
|
||||
if text[0] == 'i':
|
||||
return _spec_make(TS_INT, bits, TS_SIGN_SIGNED)
|
||||
return _spec_make(TS_FLOAT, bits, TS_SIGN_SIGNED)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _spec_make_struct - 构造 struct(深拷贝名字)
|
||||
# ============================================================
|
||||
def _spec_make_struct(kind: int, name: str) -> TypeSpec | t.CPtr:
|
||||
"""构造 struct/union/enum 类型(不驻留),失败返回 None"""
|
||||
if name is None or name[0] == '\0':
|
||||
return None
|
||||
sp: TypeSpec | t.CPtr = _spec_make(kind, 0, TS_SIGN_UNKNOWN)
|
||||
if sp is None:
|
||||
return None
|
||||
if _spec_set_struct_name(sp, name) != 0:
|
||||
return None
|
||||
return sp
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _text_to_func - 解析 "fn(p1,p2,...)->RET"
|
||||
# ============================================================
|
||||
def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr:
|
||||
"""解析函数签名文本,失败返回 None"""
|
||||
lp: str = string.strchr(text, '(')
|
||||
if lp is None:
|
||||
return None
|
||||
arrow: str = string.strstr(text, ")->")
|
||||
if arrow is None:
|
||||
return None
|
||||
# 参数段范围(lp+1 .. arrow-1)
|
||||
params_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if params_buf is None:
|
||||
return None
|
||||
params_buf[0] = '\0'
|
||||
nlen: sizet = t.CSizeT(t.CUInt64T(arrow) - t.CUInt64T(lp)) - 1
|
||||
if nlen > 0:
|
||||
string.strncpy(params_buf, lp + 1, nlen)
|
||||
params_buf[nlen] = '\0'
|
||||
is_vararg: int = 0
|
||||
if string.strstr(params_buf, "...") is not None:
|
||||
is_vararg = 1
|
||||
# 逐段解析参数(按顶层 ',' 分割;变参段 "..." 跳过)
|
||||
param_specs: sizet | t.CPtr = CompilerFactory.factory.PermPool.alloc(8 * 64)
|
||||
if param_specs is None:
|
||||
return None
|
||||
pcount: int = 0
|
||||
if nlen > 0:
|
||||
cur: str = params_buf
|
||||
while cur is not None:
|
||||
comma: str = string.strchr(cur, ',')
|
||||
seg: str = cur
|
||||
if comma is not None:
|
||||
seg_make: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if seg_make is None:
|
||||
return None
|
||||
seg_len: sizet = t.CSizeT(t.CUInt64T(comma) - t.CUInt64T(cur))
|
||||
string.strncpy(seg_make, cur, seg_len)
|
||||
seg_make[seg_len] = '\0'
|
||||
seg = seg_make
|
||||
cur = comma + 1
|
||||
else:
|
||||
cur = None
|
||||
if string.strcmp(seg, "...") == 0:
|
||||
continue
|
||||
if pcount >= 64:
|
||||
return None
|
||||
psp: TypeSpec | t.CPtr = _text_to_spec(seg, depth + 1)
|
||||
if psp is None:
|
||||
return None
|
||||
slot_p: sizet | t.CPtr = (sizet | t.CPtr)(
|
||||
t.CVoid(uint64(param_specs) + uint64(pcount * 8), t.CPtr))
|
||||
if slot_p is None:
|
||||
return None
|
||||
slot_p[0] = sizet(psp)
|
||||
pcount += 1
|
||||
ret: TypeSpec | t.CPtr = _text_to_spec(arrow + 3, depth + 1)
|
||||
if ret is None:
|
||||
return None
|
||||
sp_f: TypeSpec | t.CPtr = _spec_make(TS_FUNC, 0, TS_SIGN_UNKNOWN)
|
||||
if sp_f is None:
|
||||
return None
|
||||
sp_f.Ret = ret
|
||||
sp_f.Params = param_specs
|
||||
sp_f.ParamCount = pcount
|
||||
sp_f.IsVarArg = is_vararg
|
||||
return sp_f
|
||||
|
||||
|
||||
# ============================================================
|
||||
# InternSpec - 规范化驻留:同键只保留一份,返回驻留后的实例
|
||||
# 键 = SpecToText;超容量 fail-fast(绝不静默丢弃/复用错误实例)
|
||||
# ============================================================
|
||||
def InternSpec(arena: TypeSpecArena | t.CPtr,
|
||||
sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
|
||||
"""按规范文本键驻留 TypeSpec;失败返回 None"""
|
||||
if arena is None or sp is None:
|
||||
return sp
|
||||
if SpecArenaInit(arena, 0) != 0:
|
||||
return None
|
||||
key_buf: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if key_buf is None:
|
||||
return None
|
||||
if SpecToText(sp, key_buf, SPEC_TEXT_MAX) != 0:
|
||||
return None
|
||||
# 线性查找已有键(规模与类型种数同阶,量级不大;命中即复用)
|
||||
i: int = 0
|
||||
while i < arena.Count:
|
||||
exist_key: str = _spec_key_at(arena.Keys, i)
|
||||
if exist_key is not None and string.strcmp(exist_key, key_buf) == 0:
|
||||
slot_e: sizet | t.CPtr = (sizet | t.CPtr)(
|
||||
t.CVoid(uint64(arena.Specs) + uint64(i * 8), t.CPtr))
|
||||
if slot_e is None:
|
||||
return None
|
||||
return (TypeSpec | t.CPtr)(t.CVoid(uint64(slot_e[0]), t.CPtr))
|
||||
i += 1
|
||||
# 未命中:追加(容量检查 → fail-fast)
|
||||
if arena.Count >= arena.Cap:
|
||||
return None
|
||||
dst_key: str = _spec_key_at(arena.Keys, arena.Count)
|
||||
if dst_key is None:
|
||||
return None
|
||||
string.strcpy(dst_key, key_buf)
|
||||
slot_n: sizet | t.CPtr = (sizet | t.CPtr)(
|
||||
t.CVoid(uint64(arena.Specs) + uint64(arena.Count * 8), t.CPtr))
|
||||
if slot_n is None:
|
||||
return None
|
||||
slot_n[0] = sizet(sp)
|
||||
arena.Count += 1
|
||||
return sp
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 只读访问器(供 S3 起替换旧的字符串判定)
|
||||
# ============================================================
|
||||
def SpecIsPtr(sp: TypeSpec | t.CPtr) -> int:
|
||||
"""是否指针类型(PtrLevel>0)"""
|
||||
if sp is None:
|
||||
return 0
|
||||
if sp.PtrLevel > 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def SpecPointedTo(sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr:
|
||||
"""指针的指向类型(非指针返回 None)"""
|
||||
if sp is None or sp.Kind != TS_PTR:
|
||||
return None
|
||||
return sp.Elem
|
||||
|
||||
|
||||
def SpecIsUnsigned(sp: TypeSpec | t.CPtr) -> int:
|
||||
"""是否无符号整数(单一真源;未知返回 0)"""
|
||||
if sp is None:
|
||||
return 0
|
||||
if sp.IsSigned == TS_SIGN_UNSIGNED:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def SpecBitWidth(sp: TypeSpec | t.CPtr) -> int:
|
||||
"""位宽(非整形/浮点返回 0)"""
|
||||
if sp is None:
|
||||
return 0
|
||||
return sp.Bits
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SpecSelfCheck - S1 自检(不参与编译流程,供手动调用/后续单测)
|
||||
#
|
||||
# 构造若干类型 → 编码 → 解码 → 再编码,比较两次文本是否一致(往返一致)。
|
||||
# 返回 0=全部通过;否则返回失败用例编号(从 1 起)
|
||||
# ============================================================
|
||||
def SpecSelfCheck() -> int:
|
||||
"""TypeSpec 编解码自检,返回 0=通过 / 失败用例号"""
|
||||
arena: TypeSpecArena | t.CPtr = (TypeSpecArena | t.CPtr)(
|
||||
t.CVoid(CompilerFactory.factory.PermPool.alloc(TypeSpecArena.__sizeof__()), t.CPtr))
|
||||
if arena is None:
|
||||
return 1
|
||||
string.memset(arena, 0, TypeSpecArena.__sizeof__())
|
||||
if SpecArenaInit(arena, 64) != 0:
|
||||
return 1
|
||||
|
||||
# 1) u64
|
||||
s_u64: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
|
||||
if s_u64 is None:
|
||||
return 1
|
||||
if _check_roundtrip(s_u64, "u64") != 0:
|
||||
return 1
|
||||
|
||||
# 2) i32
|
||||
s_i32: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_INT, 32, TS_SIGN_SIGNED)
|
||||
if s_i32 is None:
|
||||
return 2
|
||||
if _check_roundtrip(s_i32, "i32") != 0:
|
||||
return 2
|
||||
|
||||
# 3) u64*
|
||||
s_p: TypeSpec | t.CPtr = NewTypePtr(arena, s_u64)
|
||||
if s_p is None:
|
||||
return 3
|
||||
if _check_roundtrip(s_p, "p:u64") != 0:
|
||||
return 3
|
||||
|
||||
# 4) i8[4]
|
||||
s_arr: TypeSpec | t.CPtr = NewTypeArray(arena, s_i32, 4)
|
||||
if s_arr is None:
|
||||
return 4
|
||||
if _check_roundtrip(s_arr, "arr[4]:i32") != 0:
|
||||
return 4
|
||||
|
||||
# 5) fn(i32,u64)->i32(变参)
|
||||
params: sizet | t.CPtr = CompilerFactory.factory.PermPool.alloc(8 * 2)
|
||||
if params is None:
|
||||
return 5
|
||||
slot0: sizet | t.CPtr = (sizet | t.CPtr)(t.CVoid(uint64(params), t.CPtr))
|
||||
if slot0 is None:
|
||||
return 5
|
||||
slot0[0] = sizet(s_i32)
|
||||
slot1: sizet | t.CPtr = (sizet | t.CPtr)(t.CVoid(uint64(params) + 8, t.CPtr))
|
||||
if slot1 is None:
|
||||
return 5
|
||||
slot1[0] = sizet(s_u64)
|
||||
s_fn: TypeSpec | t.CPtr = NewTypeFunc(arena, s_i32, params, 2, 1)
|
||||
if s_fn is None:
|
||||
return 5
|
||||
if _check_roundtrip(s_fn, "fn(i32,u64,...)->i32") != 0:
|
||||
return 5
|
||||
|
||||
# 6) 驻留去重:同一文本第二次应返回同一实例
|
||||
s_u64_again: TypeSpec | t.CPtr = NewTypeSpec(arena, TS_UINT, 64, TS_SIGN_UNSIGNED)
|
||||
if s_u64_again is None:
|
||||
return 6
|
||||
if t.CUInt64T(s_u64_again) != t.CUInt64T(s_u64):
|
||||
return 6
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _check_roundtrip - 自检辅助:编码应等于 expect,且解码再编码应一致
|
||||
# ============================================================
|
||||
def _check_roundtrip(sp: TypeSpec | t.CPtr, expect: str) -> int:
|
||||
"""编码比对 + 解码往返一致;返回 0=通过 / 1=失败"""
|
||||
if sp is None or expect is None:
|
||||
return 1
|
||||
buf1: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if buf1 is None:
|
||||
return 1
|
||||
if SpecToText(sp, buf1, SPEC_TEXT_MAX) != 0:
|
||||
return 1
|
||||
if string.strcmp(buf1, expect) != 0:
|
||||
return 1
|
||||
back: TypeSpec | t.CPtr = TextToSpec(buf1)
|
||||
if back is None:
|
||||
return 1
|
||||
buf2: str = CompilerFactory.factory.PermPool.alloc(SPEC_TEXT_MAX)
|
||||
if buf2 is None:
|
||||
return 1
|
||||
if SpecToText(back, buf2, SPEC_TEXT_MAX) != 0:
|
||||
return 1
|
||||
if string.strcmp(buf2, expect) != 0:
|
||||
return 1
|
||||
return 0
|
||||
Reference in new issue
Block a user