feat(lang): 新增 cif/celif/celse 条件编译与值引用注解 &T/&temp T,assert 改译 testcheck.check
cif 三件套:StmtGenCifMixin 负责常量求值(含 defined(模块宏) 的 Attribute 形式),链式错配与含运行时变量一律 fail-fast;删掉 c.CIf 家族。值引用:TypeGenResolve 让 CRef/CTempRef 与 t.CPtr 走同一解析路径(&void 折叠为 i8*,删除 t.CNeedPtr),CallGenBase 在调用点按形参模式自动取址(ref 只接受左值,右值 fail-fast;temp 物化临时栈),跨模块经 VpiReader/StubMergerBuild 传递模式。assert:StmtGenMixin 合成 testcheck.check(cond, None, msg),Translator 检测到 assert 时自动注入 testcheck 导入(带去重与防环),深递归守卫改用 stdio.printf + stdlib.exit(Translator 无 Gen 成员)。
This commit is contained in:
1 parent
ce50daa87a
commit
2fb648d68a
22 files changed
+556
-85
No files matched your search
@@ -850,6 +850,41 @@ def _vpi_param_annot_seg_is(src_sha1: str, cls_name: str, method_name: str, seg_
|
||||
return 1
|
||||
|
||||
|
||||
# _vpi_param_annot_seg_mode - value-reference mode of a param-annotation segment: 0=none / 1=ref / 2=temp.
|
||||
# The definition side writes `T | t.CRef` / `T | t.CTempRef`; the call side mirrors it (auto-address).
|
||||
def _vpi_param_annot_seg_mode(prm_annots: str, seg_idx: int) -> int:
|
||||
"""Return the value-reference mode encoded in a vpi param-annotation segment."""
|
||||
if prm_annots is None or seg_idx < 0: return 0
|
||||
cur: sizet = 0
|
||||
for seg in range(seg_idx):
|
||||
while prm_annots[cur] != '\0' and prm_annots[cur] != '@': cur += 1
|
||||
if prm_annots[cur] == '\0': return 0
|
||||
cur += 1
|
||||
slen: sizet = 0
|
||||
while prm_annots[cur + slen] != '\0' and prm_annots[cur + slen] != '@': slen += 1
|
||||
if slen == 0: return 0
|
||||
seg_buf: bytes = stdlib.malloc(slen + 1)
|
||||
if seg_buf is None: return 0
|
||||
string.strncpy(seg_buf, prm_annots + cur, slen)
|
||||
seg_buf[slen] = '\0'
|
||||
mode: int = 0
|
||||
if string.strstr(seg_buf, "CTempRef") is not None: mode = 2
|
||||
elif string.strstr(seg_buf, "CRef") is not None: mode = 1
|
||||
elif seg_buf[0] == '&':
|
||||
# The stub may carry the union marker (`T | t.CRef`, written by this compiler's StubGen) or
|
||||
# the source syntax (`&T` / `&temp T`, written by TPC's StubGen). Accept both, else a
|
||||
# cross-module value-reference call would silently lose its auto-address.
|
||||
q: sizet = 0
|
||||
while seg_buf[q] == ' ' or seg_buf[q] == '\t': q += 1
|
||||
if seg_buf[q] == '&':
|
||||
q += 1
|
||||
while seg_buf[q] == ' ' or seg_buf[q] == '\t': q += 1
|
||||
if slen - q >= 4 and string.strncmp(seg_buf + q, "temp", 4) == 0: mode = 2
|
||||
else: mode = 1
|
||||
stdlib.free(seg_buf)
|
||||
return mode
|
||||
|
||||
|
||||
# _ensure_vpi_param_annot_loaded - lazily load a module's vpi stub param-annotation cache.
|
||||
# Mirror of the return variant; reads the .vpi file on miss, idempotent.
|
||||
def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int:
|
||||
@@ -1192,6 +1227,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m
|
||||
return mlirlite.Void(pool)
|
||||
|
||||
has_cptr: int = 0
|
||||
has_cref: int = 0
|
||||
has_cvoid: int = 0
|
||||
first_ty: mlirlite.LLVMType* = None
|
||||
# Attributes of the segment that produced first_ty (for the has_cptr branch, N12):
|
||||
@@ -1252,7 +1288,9 @@ 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.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:
|
||||
# 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*).
|
||||
@@ -1274,7 +1312,7 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, ret_annot: str, i32_ty: m
|
||||
stdlib.free(seg_buf)
|
||||
pos += 1 # skip '|'
|
||||
|
||||
if has_cptr != 0:
|
||||
if has_cptr != 0 or has_cref != 0:
|
||||
if has_cvoid != 0: return i8_ptr_ty
|
||||
if first_ty is not None:
|
||||
# The result itself is void (e.g. an opaque typedef resolving to void): CPtr merge
|
||||
|
||||
@@ -132,6 +132,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
if ret_a == 0:
|
||||
# Container use detection: inject _list/_dict deps when an App file uses list/dict (bare annotation/ctor)
|
||||
tr._inject_auto_container_visibility(mb, tree)
|
||||
# assert lowers to testcheck.check(...): inject the testcheck dep when used
|
||||
tr._inject_auto_assert_import(mb, tree)
|
||||
# Register the App file in the store (empty incdir) and fill deps; read by
|
||||
# LookupIncludesDeps(app_sha1) when BFS expands its includes deps
|
||||
if e_r.Sha1 is not None:
|
||||
@@ -440,6 +442,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
# Inject containers on demand (append _list/_dict when includes use list/dict generics);
|
||||
# inlined to break the _list/_dict cycle
|
||||
tr_r2._inject_auto_container_visibility(mb, tree_r)
|
||||
# assert lowers to testcheck.check(...): inject the testcheck dep when used
|
||||
tr_r2._inject_auto_assert_import(mb, tree_r)
|
||||
|
||||
# Fill in-memory deps and write deps.txt (for dep-graph expansion and on-demand Phase B loading)
|
||||
deps_r2: str = tr_r2._imported_modules
|
||||
|
||||
Reference in new issue
Block a user