feat(symbols): TPC 侧同步 renum 语法糖,renum X: 展开为 class X(t.REnum):

新增 _ExpandRenumBlocks(与 _ExpandUnionBlocks 同构,只改写头行)并接入 _ExpandSoftKeywordsImpl

行首 renum 的非 renum 名字: 形态响亮失败 SyntaxError(renum 不作标识符)

同步 TransPyV/includes 46cd4b4 的解析侧支持;ExpandSoftKeywords 文档改列八种展开
This commit is contained in:
TermiNexus committed 2026-09-27 17:53:23 +08:00
1 parent e1a2821bff
commit 4346552c72
1 file changed
+51 -3
+51 -3
View File
@@ -163,7 +163,49 @@ def _ExpandUnionBlocks(Code: str) -> str:
return ''.join(out)
# ---------------------------------------------------------------------------
# Viper soft keyword `renum` (statement-level reserved word): `renum X:` is exactly
# `class X(t.REnum):` (same desugar target as TPV includes/ast/parser.vp:_parse_renumdef).
# REnum members are ordinary class-body statements (nested `class V:` variants and
# bare assignments like `None_ = 0`), so only the head line is rewritten.
# `renum` is not used as an identifier anywhere in .vp sources.
_RENUM_HEAD_RE: re.Pattern[str] = re.compile(
r'^(\s*)renum(\s+)([A-Za-z_]\w*)(\s*):([ \t]*(?:#.*)?)$'
)
_RENUM_PREFIX_RE: re.Pattern[str] = re.compile(r'^(\s*)renum\b')
def _ExpandRenumBlocks(Code: str) -> str:
"""Expand `renum Name:` into `class Name(t.REnum):` (same-line, line numbers kept).
Mirrors TPV _parse_renumdef: the body is an ordinary class body (variant classes
written as nested `class V:` plus payload-less assignments such as `None_ = 0`),
so only the head line is rewritten. A line starting with `renum` that is not the
exact `renum Name:` form fails loudly (renum is never an identifier in .vp sources).
"""
if 'renum' not in Code:
return Code
out: list[str] = []
for Lineno, raw in enumerate(Code.splitlines(keepends=True), 1):
k: int = len(raw)
while k > 0 and (raw[k - 1] == '\n' or raw[k - 1] == '\r'):
k -= 1
body: str = raw[:k]
term: str = raw[k:]
head = _RENUM_HEAD_RE.match(body)
if head is not None:
out.append(f'{head.group(1)}class {head.group(3)}(t.REnum):{head.group(5)}{term}')
continue
if _RENUM_PREFIX_RE.match(body) is not None:
raise SyntaxError(
f"renum 语法错误(行 {Lineno},原文: {body.strip()!r}):应为 `renum 名字:`"
f"(等价于 `class 名字(t.REnum):`)。renum 是语句级保留字,成员写成嵌套 "
f"`class 变体:` 或无载荷赋值(如 `None_ = 0`);非法形态一律终止编译(非静默)。"
)
out.append(raw)
return ''.join(out)
# ---------------------------------------------------------------------------
# define 常量声明(Viper 语法糖)——与 `NAME: t.CDefine = 值` **完全等价**
# ---------------------------------------------------------------------------
# 带类型 define NAME: T = <表达式> → NAME: T | t.CDefine = <表达式>
@@ -1248,7 +1290,7 @@ def EnumMemberCountMismatchError(ClassName: str, Visible: list[tuple[str, object
)
# ExpandSoftKeywords 是 Code 的纯函数(全程无全局可变状态,见其"五种展开"实现):
# ExpandSoftKeywords 是 Code 的纯函数(全程无全局可变状态,见其"八种展开"实现):
# 同一文件内容在一次编译里会被多处重复展开(Phase1 / Phase2 / 依赖扫描),
# 缓存结果避免重复正则替换与 tokenize(cProfile:_ExpandTypeDescriptors 里的
# tokenize.generate_tokens 全程 ~590 万次 TokenInfo._make)。纯函数缓存不改输出;有界防膨胀。
@@ -1282,7 +1324,11 @@ def ExpandSoftKeywords(Code: str) -> str:
_ExpandArrayPrefixAnnotations):只在注解位置生效(AnnAssign 的 ':' 之后 /
形参 / '->' 之后 / 类字段),右值列表字面量**绝不改动**;无法脱糖的注解位置
数组前缀**响亮失败**(SyntaxError,绝不静默产出 List 注解)。
七种展开都同行替换(长度可增,不增删换行),AST 行号映射保持有效。
8) `renum NAME:` → `class NAME(t.REnum):`:与手写 `class NAME(t.REnum):` 产出
**同一 AST/同一注册路径**(见 _ExpandRenumBlocks)。成员为普通类体(嵌套
`class 变体:` + 无载荷赋值)。行首 `renum` 的非 `renum 名字:` 形态**响亮失败**
(该词不在任何源码中作标识符)。
八种展开都同行替换(长度可增,不增删换行),AST 行号映射保持有效。
"""
if not Code:
return Code
@@ -1303,6 +1349,8 @@ def _ExpandSoftKeywordsImpl(Code: str) -> str:
Code = _ExpandEnumBlocks(Code)
if 'union' in Code:
Code = _ExpandUnionBlocks(Code)
if 'renum' in Code:
Code = _ExpandRenumBlocks(Code)
if 'define' in Code:
Code = _ExpandDefineConsts(Code)
if 'typedef' in Code: