From a8f6ca006da4ebce891ec6f9579a52c74fc2d0b1 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 1 Oct 2026 23:07:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(struct):=20TPC=20=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20struct=20=E5=85=B3=E9=94=AE=E5=AD=97?= =?UTF-8?q?=EF=BC=88=E5=90=AB=20C=20=E5=8A=A0=E9=80=9F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=99=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 与 TransPyV/includes 侧(c27ebc1)逐点对齐:`struct X:` / `struct X(Base):` 脱糖为 `@t.NoVTable class X(t.CStruct):`,禁止 virtual/novirtual 修饰、禁止类体内 def。 - lib/vast/Parser.py:软关键字分派(语句起始 + 后随标识符;`struct = 5` 不受影响)、 _ParseStructDef(复用 _ParseClassDef 全路径 + 合成 @t.NoVTable + 追加 t.CStruct 标记基类 + 类体禁 def 校验)、_StructSyntaxError 报文、_ParseVirtualModified 显式拦截 `virtual/novirtual struct`;@deco 前缀同样支持。 - lib/vast_c/vast_c.c:同构实现(ParseStatement / ParseDecorated 分派、 ParseStructDef、ParseVirtualModified 拦截)。 - lib/vast_c/_parser.pyd:按 README §4.3 的命令重建(gcc 15.2.0)。 验证(两条路径逐一对照):bases=[t.CStruct] / [Base, t.CStruct]、 decos=[t.NoVTable];`virtual struct` 与 `struct 内 def` 均 fail-fast; `struct = 5` 仍解析为普通赋值。 --- lib/vast/Parser.py | 90 +++++++++++++++++++++++++++++++++++++++++ lib/vast_c/_parser.pyd | Bin 215440 -> 217027 bytes lib/vast_c/vast_c.c | 87 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) diff --git a/lib/vast/Parser.py b/lib/vast/Parser.py index 7519cbb..f050999 100644 --- a/lib/vast/Parser.py +++ b/lib/vast/Parser.py @@ -62,6 +62,26 @@ _VIRTUAL_EXAMPLE: str = ( 'novirtual class B: novirtual def helper(self) -> int: ...' ) +# ====================================================================== +# struct 纯数据类型定义关键字(软关键字) +# ====================================================================== +# 语法:`struct X:` / `struct X(Base):`(与 class 同形,含类型参数 [T] 与关键字实参) +# 语义(用户 2026-10-01 定):与 class 同形,但**只能表示数据类型**: +# - 禁止 virtual / novirtual 修饰(见 _ParseVirtualModified 的显式拦截); +# - 禁止类体内定义 def(见 _ParseStructDef 的 fail-fast); +# - 解析期合成 `@t.NoVTable` 装饰器 + 追加 `t.CStruct` 标记基类, +# 与手写 `@t.NoVTable class X(t.CStruct):` 逐字段同形 ⇒ 下游 +# (HandlesClassDef._resolve_class_flags / _MARKER_BASES)零新增判据。 +# - 允许出现在 REnum 内部(REnum 变体本就是嵌套 ClassDef),也允许 struct 内 +# 再写 struct(与 class 内写 class 同口径)。 +# 软关键字边界:只在"语句起始 + 后随标识符"时判定,故 `struct = 5` / `x.struct` +# 等作标识符的写法逐字不变。 +_STRUCT_KEYWORD: str = 'struct' +_STRUCT_EXAMPLE: str = ( + 'struct Point: x: int / struct Point: x: int(换行缩进)y: int / ' + 'struct Node(Base): value: int' +) + class Parser(ExprParserMixin): """Viper/Python 完整语法分析器。""" @@ -145,6 +165,10 @@ class Parser(ExprParserMixin): return self._ParseFunctionDef() if v == 'class': return self._ParseClassDef() + # struct 纯数据类型定义(软关键字):仅"语句起始 + 后随标识符"时判定, + # 故 `struct = 5` / `x.struct` 等作标识符的写法逐字不变。 + if v == _STRUCT_KEYWORD and self._Peek(1).Type == NAME: + return self._ParseStructDef() if v == 'if': return self._ParseIf() if v == 'while': @@ -586,6 +610,8 @@ class Parser(ExprParserMixin): return self._ParseFunctionDef(is_async=True, decorators=decorator_list) if tok.Type == NAME and tok.Value == 'class': return self._ParseClassDef(decorators=decorator_list) + if tok.Type == NAME and tok.Value == _STRUCT_KEYWORD and self._Peek(1).Type == NAME: + return self._ParseStructDef(decorators=decorator_list) if tok.Type == NAME and tok.Value in _VIRTUAL_MARKERS: # `@deco` 与 `virtual class`/`virtual def` 组合:合成标记追加在既有装饰器之后 return self._ParseVirtualModified(decorators=decorator_list) @@ -643,6 +669,13 @@ class Parser(ExprParserMixin): and nxt.Value not in _DEF_ALIASES): nxt_text: str = ('(行尾)' if nxt.Type in (NEWLINE, NL, ENDMARKER) else repr(nxt.Value)) + if nxt.Type == NAME and nxt.Value == _STRUCT_KEYWORD: + # struct 是纯数据类型:禁止 virtual / novirtual 修饰(用户 2026-10-01 定)。 + # 单独报文(而不是落到通用"后随非 class/def")以便直接给出修法。 + raise self._StructSyntaxError( + f'{mod.Value} struct 非法:struct 禁止 virtual/novirtual 修饰', mod, + 'struct 天然无虚表(解析期已合成 @t.NoVTable),请直接写 `struct X:`;' + '需要虚表语义请改用 class。') raise self._VirtualSyntaxError( f"{mod.Value!r} 后随 {nxt_text}(非 class/def)", mod, f"`{mod.Value}` 只在 class/def(def 的别名 fn/fun/func/function)" @@ -663,6 +696,63 @@ class Parser(ExprParserMixin): return self._ParseClassDef(decorators=deco_list) return self._ParseFunctionDef(decorators=deco_list) + # ================================================================== + # struct 纯数据类型定义(软关键字:`struct X:` / `struct X(Base):`) + # ================================================================== + def _StructSyntaxError(self, detail: str, tok: Token, extra: str = '') -> SyntaxError: + """构造 struct 非法形态的 fail-fast 报文(与 _VirtualSyntaxError 同结构)。 + + 含 行:列 + 源码片段 + struct 的三条约束 + 正确示例;行尾附 `at line N` + 供 TPC 既有诊断路径兜底提取行号(见 HandlesImports._ParseFailureSite)。 + """ + return SyntaxError( + f"[TPC] struct 定义非法({detail}):行 {tok.Line} 列 {tok.Col}," + f"源码片段 {self._SourceLine(tok.Line).strip()!r}。" + f"struct 与 class 同形,但**只能表示数据类型**:" + f"① 禁止 virtual / novirtual 修饰(struct 天然无虚表,已内置 @t.NoVTable);" + f"② 禁止在 struct 内定义 def(需要方法请改用 class);" + f"③ 允许在 REnum 内作为变体、也允许 struct 内再写 struct。" + f"正确示例:{_STRUCT_EXAMPLE}。" + + (f" {extra}" if extra else '') + + " (struct 的约束不会被静默忽略:非法形态一律终止编译)" + + f" at line {tok.Line}" + ) + + def _ParseStructDef(self, decorators: list[N.expr] | None = None) -> N.ClassDef: + """`struct X:` / `struct X(Base):` → 与 `@t.NoVTable class X(t.CStruct):` + 逐字段同形的 ClassDef(与 TPV 的 _parse_structdef 同口径)。 + + 实现:复用 _ParseClassDef 的完整解析路径(类型参数 / 基类 / 关键字实参 / + 类体套件),只在**解析前后**补三件事: + · 解析前把合成的 `@t.NoVTable` 追加进装饰器列表(与 virtual/novirtual + 同款表示)⇒ 类级强制无虚表,即使父类带虚表; + · 解析后把 `t.CStruct` 标记基类**追加**到 bases 末尾(不提位用户基类, + 真实父类解析顺序不变)⇒ 数据类语义(_MARKER_BASES 认它,不当真实父类); + · 解析后校验类体**直接子节点**里没有 def —— struct 只能表示数据类型。 + _ParseClassDef 的首个 `_Next()` 消费的正是 `struct` 关键字本身,故本函数 + 不预先消费,行号/列号与写法均继承自该 token。 + """ + start: Token = self._Peek() # struct(由 _ParseClassDef 的 _Next() 消费) + deco: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), + attr='NoVTable', ctx=N.Load()) + self._FixLoc(deco, start) + deco_list: list[N.expr] = list(decorators or []) + deco_list.append(deco) + node: N.ClassDef = self._ParseClassDef(decorators=deco_list) + marker_base: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()), + attr='CStruct', ctx=N.Load()) + self._FixLoc(marker_base, start) + node.bases.append(marker_base) + for item in node.body: + if isinstance(item, N.FunctionDef): + bad: Token = start + raise self._StructSyntaxError( + f"struct {node.name!r} 内定义 def {getattr(item, 'name', '(anonymous)')!r}", + bad, + 'struct 只表示数据类型(与 C 的 struct 同口径);' + '若确实需要方法与虚表,请把该类型写成 class。') + return node + # ================================================================== # 函数定义(含软关键字 fn/fun/func/function) # ================================================================== diff --git a/lib/vast_c/_parser.pyd b/lib/vast_c/_parser.pyd index 306d403f28aedb813eb2fba900f220383e593cc1..8041032b2924a53ec06e547505cb250b63581f23 100644 GIT binary patch delta 47994 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 btQjzkaQECfctqqsF+{J_{gp%YyE6U@Dm_vz diff --git a/lib/vast_c/vast_c.c b/lib/vast_c/vast_c.c index bb2fefe..a304044 100644 --- a/lib/vast_c/vast_c.c +++ b/lib/vast_c/vast_c.c @@ -4343,6 +4343,7 @@ static PyObject *ParseDelete(Parser *P); static PyObject *ParseAssert(Parser *P); static PyObject *ParseDecorated(Parser *P); static PyObject *ParseVirtualModified(Parser *P, PyObject *Decorators); +static PyObject *ParseStructDef(Parser *P, PyObject *Decorators); static PyObject *ParseTypeParams(Parser *P); static PyObject *ParseExceptHandler(Parser *P); static PyObject *ParseTargetList(Parser *P); @@ -4429,6 +4430,11 @@ static PyObject *ParseStatement(Parser *P) { if (TokIsName(T, "class")) { return ParseClassDef(P, NULL); } + /* struct 纯数据类型定义(软关键字:仅"语句起始 + 后随标识符"生效, + * 故 `struct = 5` / `x.struct` 作标识符的写法不受影响) */ + if (TokIsName(T, "struct") && PeekTok(P, 1)->Kind == TK_NAME) { + return ParseStructDef(P, NULL); + } if (TokIsName(T, "if")) { return ParseIf(P); } @@ -5161,6 +5167,10 @@ static PyObject *ParseDecorated(Parser *P) { if (T->Kind == TK_NAME && TokIsName(T, "class")) { return ParseClassDef(P, DecoratorList); } + if (T->Kind == TK_NAME && TokIsName(T, "struct") + && PeekTok(P, 1)->Kind == TK_NAME) { + return ParseStructDef(P, DecoratorList); + } if (T->Kind == TK_NAME && (TokIsName(T, "virtual") || TokIsName(T, "novirtual"))) { return ParseVirtualModified(P, DecoratorList); } @@ -5189,6 +5199,14 @@ static PyObject *ParseVirtualModified(Parser *P, PyObject *Decorators) { IsDef = 1; } } + if (Nxt->Kind == TK_NAME && TokIsName(Nxt, "struct")) { + /* struct 是纯数据类型:禁止 virtual / novirtual 修饰(用户 2026-10-01 定)。 + * struct 解析期已合成 @t.NoVTable,无需也无法再显式声明虚/非虚。 */ + SyntaxErrorAt(P, Mod, + "virtual/novirtual is not allowed on struct " + "(struct is data-only, use class for vtable)"); + return NULL; + } if (!IsClass && !IsDef) { SyntaxErrorAt(P, Mod, "virtual/novirtual must precede class/def"); return NULL; @@ -5730,6 +5748,75 @@ static PyObject *ParseClassDef(Parser *P, PyObject *Decorators) { return Node; } +/* struct 纯数据类型定义(对齐 vast Parser._ParseStructDef): + * `struct X:` / `struct X(Base):` ≡ `@t.NoVTable class X(t.CStruct):`。 + * 复用 ParseClassDef 的完整解析路径(类型参数/基类/关键字实参/类体套件)—— + * ParseClassDef 的首个 NextTok 消费的正是 `struct` 关键字本身,故此处不预消费。 + * 解析前后各补:合成 @t.NoVTable 装饰器(类级强制无虚表)、追加 t.CStruct + * 标记基类(数据类语义,_MARKER_BASES 认它)、校验类体内没有 def。 */ +static PyObject *ParseStructDef(Parser *P, PyObject *Decorators) { + Token *Start = PeekTok(P, 0); /* struct */ + PyObject *Deco = MakeTAttrNode(P, "NoVTable"); + if (Deco == NULL) { + return NULL; + } + FixLoc(P, Deco, Start); + PyObject *DecoList = NewList(); + if (DecoList == NULL) { + Py_DECREF(Deco); + return NULL; + } + if (Decorators != NULL) { + Py_ssize_t N = PyList_GET_SIZE(Decorators); + for (Py_ssize_t I = 0; I < N; I++) { + PyList_Append(DecoList, PyList_GET_ITEM(Decorators, I)); + } + } + PyList_Append(DecoList, Deco); + Py_DECREF(Deco); + PyObject *Node = ParseClassDef(P, DecoList); + Py_DECREF(DecoList); + if (Node == NULL) { + return NULL; + } + /* 数据类标记基类:追加在用户基类之后(真实父类解析顺序不变) */ + PyObject *Bases = PyObject_GetAttrString(Node, "bases"); + if (Bases == NULL) { + PyErr_Clear(); + } else { + PyObject *MarkerBase = MakeTAttrNode(P, "CStruct"); + if (MarkerBase == NULL) { + Py_DECREF(Bases); + Py_DECREF(Node); + return NULL; + } + FixLoc(P, MarkerBase, Start); + PyList_Append(Bases, MarkerBase); + Py_DECREF(MarkerBase); + Py_DECREF(Bases); + } + /* struct 禁止 def:检查类体直接子节点(嵌套 struct 由其自身解析自检) */ + PyObject *Body = PyObject_GetAttrString(Node, "body"); + if (Body == NULL) { + PyErr_Clear(); + return Node; + } + Py_ssize_t BN = PyList_GET_SIZE(Body); + for (Py_ssize_t I = 0; I < BN; I++) { + PyObject *Item = PyList_GET_ITEM(Body, I); + if (Item != NULL && NodeIs(Item, "FunctionDef")) { + SyntaxErrorAt(P, Start, + "def is not allowed inside struct " + "(struct is data-only, use class for methods)"); + Py_DECREF(Body); + Py_DECREF(Node); + return NULL; + } + } + Py_DECREF(Body); + return Node; +} + /* 语句块(套件) */ static PyObject *ParseSuiteImpl(Parser *P) { if (PeekTok(P, 0)->Kind == TK_NEWLINE) {