diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index e9fb474..03c1f18 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -367,8 +367,16 @@ def _WillFreeMergeTag(fn: ast.FunctionDef*, tag: ast.AST*, mask: int) -> int: is_wf: int = string.strcmp(tnm, "willFree") is_esc: int = string.strcmp(tnm, "escape") is_nesc: int = string.strcmp(tnm, "noescape") - if is_wf != 0 and is_esc != 0 and is_nesc != 0: - fatal_error(tag, "@life(...) accepts only `willFree()` / `escape()` / `noescape()` tags", "LifetimeError") + # A1(§14):stores ≡ escape("确定存进长命存储"的强声明)、borrows ≡ noescape(借出口径)。 + # 二者复用同一对契约位,位本身由 compute_escape_directives 收。 + is_st: int = string.strcmp(tnm, "stores") + is_bw: int = string.strcmp(tnm, "borrows") + # A2/A3 的标签(ret / owns)先**显式**报"未实现",不做静默忽略(静默 = 用户以为标注生效了)。 + if string.strcmp(tnm, "owns") == 0 or string.strcmp(tnm, "ret") == 0: + fatal_error(tag, f"@life tag `{tnm}(...)` is not implemented yet (planned A2/A3); use willFree/escape/noescape/stores/borrows for now", "LifetimeError") + return mask + if is_wf != 0 and is_esc != 0 and is_nesc != 0 and is_st != 0 and is_bw != 0: + fatal_error(tag, "@life(...) accepts only `willFree(...)` / `escape(...)` / `noescape(...)` / `stores(...)` / `borrows(...)` tags", "LifetimeError") return mask if tc.args is None or len(tc.args) == 0: fatal_error(tag, f"@life tag `{tnm}(...)` needs at least one parameter name or 0-based position", "LifetimeError") @@ -422,6 +430,9 @@ def compute_escape_directives(fd: ast.AST*, out: sizet*) -> int: if tnm2 is None: continue is_esc2: int = string.strcmp(tnm2, "escape") is_nesc2: int = string.strcmp(tnm2, "noescape") + # A1(§14):stores 归到"强制逃逸"位、borrows 归到"强制不逃逸"位(复用同一对契约位) + if string.strcmp(tnm2, "stores") == 0: is_esc2 = 0 + if string.strcmp(tnm2, "borrows") == 0: is_nesc2 = 0 if is_esc2 != 0 and is_nesc2 != 0: continue if tcl.args is None or len(tcl.args) == 0: fatal_error(tg, f"@life tag `{tnm2}(...)` needs at least one parameter name or 0-based position", "LifetimeError") @@ -434,12 +445,12 @@ def compute_escape_directives(fd: ast.AST*, out: sizet*) -> int: if idx2 < 0: continue if is_esc2 == 0: if ((int(out[1]) >> idx2) & 1) != 0: - fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape(...) and noescape(...)", "LifetimeError") + fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape/stores(...) and noescape/borrows(...)", "LifetimeError") continue out[0] = out[0] | (sizet(1) << idx2) else: if ((int(out[0]) >> idx2) & 1) != 0: - fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape(...) and noescape(...)", "LifetimeError") + fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape/stores(...) and noescape/borrows(...)", "LifetimeError") continue out[1] = out[1] | (sizet(1) << idx2) return 0