feat(static): static 修饰符改为语句起始前置 + 新增 static def(旧的注解位置响亮失败)
vast/Parser.py:ParseStatement 与 _ParseDecorated 新增 static def 分派(判据要求第 2 个 token 是 def,故 static = 5 / static x = 5 不会被误吃成函数定义);新增 _ParseStaticDef,镜像 _ParseExportDef 但**不改写返回注解**、而是在既有装饰器之后合成 @t.CStatic SymbolUtils.py:_TYPE_DESCRIPTOR_MARKERS 删掉 static;新增 _StaticPositionSyntaxError 与 _InStaticOldAnnotationPosition,旧注解位置(名字: static 类型)一律 SyntaxError 并提示前置形式,绝不静默改写;_EXPORT_EXTERN_MODIFIERS 加入 static,_ExpandExportExternVar 新增前置分支——export/extern 追加在类型右侧(或 t.CExport / 或 t.State),static **前置在类型最左**(t.CStatic 加竖线),允许初值;数组前缀展开仍在修饰符展开之前 与 includes/ast/parser.vp 的 pending_static 通道同源:static 名字: 类型 = 值 产出与手写 名字: t.CStatic | 类型、装饰器 @t.CStatic 逐字段同形
This commit is contained in:
1 parent
f9957787a0
commit
e5a6616f8b
2 files changed
+210
-49
No files matched your search
+142
-49
@@ -357,12 +357,13 @@ def _ExpandTypedefs(Code: str) -> str:
|
||||
# (BinOp(BitOr, Attribute(t,'CConst'), <类型>)),产出与手写形态逐字段同形。
|
||||
#
|
||||
# 软关键字边界(唯一识别面 = "注解位置 + token 相邻",与 array 那次同口径):
|
||||
# const/volatile/static 只在该位置生效——修饰符串的前一个 token 是 `:` 且再前一个是
|
||||
# const/volatile 只在该位置生效——修饰符串的前一个 token 是 `:` 且再前一个是
|
||||
# Name(注解目标:`a:` / `self.x:` / 形参名),或前一个 token 是 `->`(返回注解)。
|
||||
# `static` 与另两者同源:ViperOS 驱动广泛写 `pack_head: static uint32 = 0`,
|
||||
# 注解位置未被消费时会退化成一个叫 static 的"类名"(被建成 opaque 结构体
|
||||
# `@a = global %"<sha1>.static" zeroinitializer`,llvm-link 报 invalid type for
|
||||
# null constant)——故必须与 const/volatile 同路径脱糖为 `t.CStatic | T`。
|
||||
# **`static` 已从注解位置迁出**(不再与 const/volatile 同源):注解位置不再接受
|
||||
# `名字: static 类型`(如旧的 `pack_head: static uint32 = 0`),必须改写为**语句
|
||||
# 起始前置**形式——变量 `static 名字: 类型 = 值`、函数 `static def 名字(...)`
|
||||
# (见 _ExpandExportExternVar 的 static 前置分支与 vast.Parser._ParseStaticDef);
|
||||
# 旧注解位置一律**响亮失败**(见下),不再脱糖为 `t.CStatic | T`。
|
||||
# 非类型位置**原样保留**为普通标识符(不做词法保留字):
|
||||
# - `t.attr.const()`(TransPyV/Test/App/attr_test.vp:142,全仓 .vp 代码内唯一出现)
|
||||
# - `const = 5` / `x = const` / `d = {"k": const}`
|
||||
@@ -370,19 +371,21 @@ def _ExpandTypedefs(Code: str) -> str:
|
||||
# 故 openssl/*.vp 等 C 原型注释里的 `const char *`(全仓 275 处)逐字不变。
|
||||
#
|
||||
# 非法形态**响亮失败**(SyntaxError,非静默,不丢描述符):
|
||||
# `a: const`(缺类型)/ `a: const = 1` / `a: const 1`(后随非类型)/ 裸 `const` 语句。
|
||||
# `a: const`(缺类型)/ `a: const = 1` / `a: const 1`(后随非类型)/ 裸 `const` 语句;
|
||||
# **注解位置的 `static`**(如 `memory_regions: static memory_region* = None`):
|
||||
# 已迁移为前置形式,旧写法一律终止编译。
|
||||
# 报文含 行:列 + 源码片段 + 期望形态 + 正确示例(文件名由调用方的 SyntaxError
|
||||
# 上报路径补全,与 _ExpandTypedefs / TPV dump_parse_traceback 同约定)。
|
||||
_TYPE_DESCRIPTOR_MARKERS: dict[str, str] = {
|
||||
'const': 'CConst', 'volatile': 'CVolatile', 'static': 'CStatic',
|
||||
'const': 'CConst', 'volatile': 'CVolatile',
|
||||
}
|
||||
_DESCRIPTOR_SKIP_TYPES: tuple[int, ...] = (tokenize.COMMENT, tokenize.NL)
|
||||
_DESCRIPTOR_HINT: str = (
|
||||
'`名字: const 类型` / `名字: volatile 类型` / `名字: static 类型`'
|
||||
'`名字: const 类型` / `名字: volatile 类型`'
|
||||
'(可组合:`名字: const volatile 类型`)'
|
||||
)
|
||||
_DESCRIPTOR_EXAMPLE: str = (
|
||||
'a: const int / a: volatile int / a: static uint32 / a: const volatile t.CInt32T / '
|
||||
'a: const int / a: volatile int / a: const volatile t.CInt32T / '
|
||||
'def f(p: const rawptr[Foo]) -> const int'
|
||||
)
|
||||
|
||||
@@ -412,12 +415,60 @@ def _TypeDescriptorSyntaxError(Detail: str, Lineno: int, Col: int, Snippet: str)
|
||||
"""构造类型描述符非法形态的 fail-fast 报文(行:列 + 源码片段 + 期望形态 + 正确示例)。"""
|
||||
return SyntaxError(
|
||||
f"[TPC] 类型描述符非法({Detail}):行 {Lineno} 列 {Col},源码片段 {Snippet.strip()!r}。"
|
||||
f"const/volatile/static 是只在**类型位置**生效的软关键字,必须写成 {_DESCRIPTOR_HINT};"
|
||||
f"const/volatile 是只在**类型位置**生效的软关键字,必须写成 {_DESCRIPTOR_HINT};"
|
||||
f"正确示例:{_DESCRIPTOR_EXAMPLE}。"
|
||||
f"(描述符不会被静默忽略:缺类型 / 后随非类型 / 裸用一律终止编译)"
|
||||
)
|
||||
|
||||
|
||||
def _StaticPositionSyntaxError(Lineno: int, Col: int, Snippet: str) -> SyntaxError:
|
||||
"""构造旧位置 static(注解位置)的 fail-fast 报文。
|
||||
|
||||
注解位置的 `static` 已迁移为**语句起始前置**修饰符(`static 名字: 类型 = 值`);
|
||||
旧写法 `名字: static 类型 = 值` 一律终止编译,绝不静默改写。
|
||||
"""
|
||||
return SyntaxError(
|
||||
f"[TPC] 注解位置的 static 已不再支持:行 {Lineno} 列 {Col},"
|
||||
f"源码片段 {Snippet.strip()!r}。"
|
||||
f"请写成前置形式 `static 名字: 类型 = 值`"
|
||||
f"(等价 `名字: t.CStatic | 类型 = 值`);"
|
||||
f"正确示例:`static memory_regions: memory_region* = None` / "
|
||||
f"`static pack_head: uint32 = 0`。"
|
||||
f"(旧写法 `名字: static 类型` 已删除,绝不静默改写)"
|
||||
)
|
||||
|
||||
|
||||
def _InStaticOldAnnotationPosition(Tokens: list, Index: int) -> bool:
|
||||
"""`Index` 处的 `static` 是否处于**旧**注解位置(`名字: static 类型` / `-> static 类型`)。
|
||||
|
||||
与 _ExpandTypeDescriptors 的注解位置判据同口径,并额外回溯 `const` / `volatile` /
|
||||
`static` / `|`,以覆盖 `a: const static T` 这类组合旧形态。
|
||||
"""
|
||||
j: int = Index
|
||||
Guard: int = 0
|
||||
while j >= 0 and Guard < 64:
|
||||
PrevIdx: int = _PrevSignificantTokenIndex(Tokens, j)
|
||||
if PrevIdx < 0:
|
||||
return False
|
||||
Prev = Tokens[PrevIdx]
|
||||
if Prev.string == '->':
|
||||
return True
|
||||
if Prev.string == ':':
|
||||
BeforeIdx: int = _PrevSignificantTokenIndex(Tokens, PrevIdx)
|
||||
return BeforeIdx >= 0 and Tokens[BeforeIdx].type == tokenize.NAME
|
||||
if Prev.string == '|':
|
||||
j = PrevIdx
|
||||
Guard += 1
|
||||
continue
|
||||
if Prev.type == tokenize.NAME and (
|
||||
Prev.string in _TYPE_DESCRIPTOR_MARKERS or Prev.string == 'static'):
|
||||
j = PrevIdx
|
||||
Guard += 1
|
||||
continue
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
# C-style leading array declarator `const [N]T`: textual desugar into
|
||||
# `t.CArray[T, N]` (same shape as TPV includes/ast/parser.vp:_parse_array_prefix_declarator).
|
||||
_TYPE_BRACKET_OPENERS: frozenset[str] = frozenset({'(', '[', '{'})
|
||||
@@ -576,13 +627,14 @@ def _AtAnnotationColon(Tokens: list, ColonIdx: int, Stack: list) -> bool:
|
||||
if BoundIdx < 0:
|
||||
return True
|
||||
Bound = Tokens[BoundIdx]
|
||||
# `export 名字: T` / `extern 名字: T`(变量声明的存储类修饰符,见
|
||||
# _ExpandExportExternVar):修饰符与名字之间已构成语句起始,同样算注解位置。
|
||||
# 本判据必须在 export/extern 展开**之前**成立——`[N]T` 数组前缀与
|
||||
# `export 名字: T` / `extern 名字: T` / `static 名字: T`(变量声明的存储类
|
||||
# 修饰符,见 _ExpandExportExternVar):修饰符与名字之间已构成语句起始,同样算
|
||||
# 注解位置。本判据必须在修饰符展开**之前**成立——`[N]T` 数组前缀与
|
||||
# `__attribute__(...)` 两条路径都先于该展开运行,靠它把
|
||||
# `export gdt: [7]gdt_entry = []` 正常脱糖成 `export gdt: t.CArray[gdt_entry, 7] = []`
|
||||
# (若等到展开后再插入 ` | t.CExport`,`|` 不在 _TYPE_EXPR_STOP_TOKENS 中,
|
||||
# 会被并进数组元素类型 → `t.CArray[gdt_entry | t.CExport, 7]`)。
|
||||
# `export gdt: [7]gdt_entry = []` / `static g: [7]int = []` 正常脱糖成
|
||||
# `t.CArray[...]` 形态(若等到展开后再插入 ` | t.CExport` / 前置 `t.CStatic | `,
|
||||
# `|` 不在 _TYPE_EXPR_STOP_TOKENS 中,会被并进数组元素类型 →
|
||||
# `t.CArray[gdt_entry | t.CExport, 7]`)。
|
||||
if Bound.type == tokenize.NAME and Bound.string in _EXPORT_EXTERN_MODIFIERS:
|
||||
return True
|
||||
return Bound.type in _ARRAY_STMT_BOUNDARY or Bound.string == ';'
|
||||
@@ -677,25 +729,32 @@ def _ExpandArrayPrefixAnnotations(Code: str) -> str:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 变量声明的存储类修饰符 export / extern(语句级软关键字)——与 TPV
|
||||
# includes/ast/parser.vp:_parse_export_extern_var **同一标记、同一消费路径**:
|
||||
# 变量声明的存储类修饰符 export / extern / static(语句级软关键字)——与 TPV
|
||||
# includes/ast/parser.vp **同一标记、同一消费路径**:
|
||||
# export 名字: T [= 初值] → 名字: T | t.CExport [= 初值]
|
||||
# (本模块**定义**:定义端裸名,不加模块 SHA1 头;内联汇编 / C 符号对接必需。
|
||||
# 无初值时按既有零初始化全局定义处理,如 `export tss_buf: [104]uint8`。)
|
||||
# extern 名字: T → 名字: T | t.State
|
||||
# (**仅声明**:t.State = t.CExtern | t.CExport ⇒ 定义端 `@裸名 = external global T`。
|
||||
# extern 是外部定义,**不允许**初值 ⇒ 带 `= 初值` 一律终止编译。)
|
||||
# 与函数形态(`export def f()` / `export f()` / `extern def f()`,vast 既有处理)
|
||||
# 由第三个 token 区分:`:` 是变量,`(` / `[` 是函数 ⇒ 函数语义逐字不变。
|
||||
# `export` / `extern` 不在任何 .vp 源码中作标识符(仅本语法与注释使用)。
|
||||
# static 名字: T [= 初值] → 名字: t.CStatic | T [= 初值]
|
||||
# (存储类标记**前置**在类型联合最左,与 TPV `_ParseStaticModified` 的
|
||||
# `pending_static` 通道同源——`static 名字: T` → `名字: t.CStatic | T`;允许初值。
|
||||
# 产出与手写 `名字: t.CStatic | T` / 装饰器 `@t.CStatic` 逐字段同形。
|
||||
# 旧注解位置写法 `名字: static T` 已删除,见 _StaticPositionSyntaxError。)
|
||||
# 与函数形态(`export def f()` / `export f()` / `extern def f()` / `static def f()`,
|
||||
# vast 既有处理)由第三个 token 区分:`:` 是变量,`(` / `[` 是函数 ⇒ 函数语义逐字不变。
|
||||
# `export` / `extern` / `static` 不在任何 .vp 源码中作标识符(仅本语法与注释使用)。
|
||||
# ---------------------------------------------------------------------------
|
||||
_EXPORT_EXTERN_MODIFIERS: frozenset[str] = frozenset({'export', 'extern'})
|
||||
_EXPORT_EXTERN_MODIFIERS: frozenset[str] = frozenset({'export', 'extern', 'static'})
|
||||
_EXPORT_EXTERN_HINT: str = (
|
||||
'`export 名字: 类型 [= 初值]`(裸名导出,等价 `名字: 类型 | t.CExport`);'
|
||||
'`extern 名字: 类型`(仅声明,等价 `名字: 类型 | t.State`,**不允许初值**)'
|
||||
'`extern 名字: 类型`(仅声明,等价 `名字: 类型 | t.State`,**不允许初值**);'
|
||||
'`static 名字: 类型 [= 初值]`(等价 `名字: t.CStatic | 类型`)'
|
||||
)
|
||||
_EXPORT_EXTERN_EXAMPLE: str = (
|
||||
'export gdt: [7]gdt_entry = [] / export tss_buf: [104]uint8 / extern a: int'
|
||||
'export gdt: [7]gdt_entry = [] / export tss_buf: [104]uint8 / extern a: int / '
|
||||
'static memory_regions: memory_region* = None'
|
||||
)
|
||||
|
||||
|
||||
@@ -711,22 +770,26 @@ def _ExportExternSyntaxError(Detail: str, Lineno: int, Col: int,
|
||||
|
||||
|
||||
def _ExpandExportExternVar(Code: str) -> str:
|
||||
"""把 `export 名字: T [= 初值]` / `extern 名字: T` 展开为带存储类标记的注解。
|
||||
"""把 `export 名字: T [= 初值]` / `extern 名字: T` / `static 名字: T [= 初值]`
|
||||
展开为带存储类标记的注解。
|
||||
|
||||
与 TPV `_parse_export_extern_var` 同口径:export → `| t.CExport`;
|
||||
extern → `| t.State`;extern 带初值 ⇒ **响亮失败**(SyntaxError)。
|
||||
与 TPV 同口径:export → 类型**右侧追加** `| t.CExport`;extern → 追加 `| t.State`
|
||||
(extern 带初值 ⇒ **响亮失败** SyntaxError);static → 类型**左侧前置** `t.CStatic | `
|
||||
(与 TransPyV `_ParseStaticModified` / `pending_static` 通道同源——`static 名字: T`
|
||||
→ `名字: t.CStatic | T`,亦与手写 `名字: t.CStatic | T` / `@t.CStatic` 逐字段同形;
|
||||
static **允许**初值)。
|
||||
|
||||
- 只在"语句起始(可缩进)+ export/extern + 标识符 + `:`"形态触发;函数形态
|
||||
(`export def f()` / `export f()` / `extern def f()`)第三个 token 不是 `:`
|
||||
⇒ 不命中,vast 的既有函数处理逐字不变。
|
||||
- 只在"语句起始(可缩进)+ export/extern/static + 标识符 + `:`"形态触发;函数形态
|
||||
(`export def f()` / `export f()` / `extern def f()` / `static def f()`)第三个
|
||||
token 不是 `:` ⇒ 不命中,vast 的既有函数处理逐字不变。
|
||||
- **必须排在 `_ExpandArrayPrefixAnnotations` 之后**:此时注解已是规范形态
|
||||
(`t.CArray[T, N]` / `t.CConst | ...`),插入点由 `_ScanAnnotationTypeEnd`
|
||||
确定;`|` 不在 `_TYPE_EXPR_STOP_TOKENS` 中,若在数组前缀展开前插入会被
|
||||
并进数组元素类型(`t.CArray[gdt_entry | t.CExport, 7]`)。数组前缀之所以
|
||||
仍能脱糖,靠的是 `_AtAnnotationColon` 已把 export/extern 认作语句边界。
|
||||
- 同行编辑(删修饰符 + 插标记),不增删换行 ⇒ 行号映射保持有效。
|
||||
仍能脱糖,靠的是 `_AtAnnotationColon` 已把 export/extern/static 认作语句边界。
|
||||
- 同行编辑(删修饰符 + 插/前置标记),不增删换行 ⇒ 行号映射保持有效。
|
||||
"""
|
||||
if 'export' not in Code and 'extern' not in Code:
|
||||
if 'export' not in Code and 'extern' not in Code and 'static' not in Code:
|
||||
return Code
|
||||
try:
|
||||
Tokens: list = list(tokenize.generate_tokens(io.StringIO(Code).readline))
|
||||
@@ -755,6 +818,7 @@ def _ExpandExportExternVar(Code: str) -> str:
|
||||
raise _ExportExternSyntaxError(
|
||||
'缺少类型注解', Line, Tok.start[1] + 1, Snippet)
|
||||
IsExtern: bool = Tok.string == 'extern'
|
||||
IsStatic: bool = Tok.string == 'static'
|
||||
AfterIdx: int = _NextSignificantTokenIndex(Tokens, TypeEnd - 1)
|
||||
if (IsExtern and AfterIdx >= 0
|
||||
and Tokens[AfterIdx].string == '='):
|
||||
@@ -767,10 +831,19 @@ def _ExpandExportExternVar(Code: str) -> str:
|
||||
DelEnd: int = NameTok.start[1]
|
||||
DelOrig: str = Snippet[DelStart:DelEnd]
|
||||
Edits.append((Line, DelStart, DelEnd, '', DelOrig))
|
||||
# 编辑 2:在注解类型终点插入存储类标记。
|
||||
InsAt: tuple[int, int] = Tokens[TypeEnd - 1].end
|
||||
Marker: str = ' | t.State' if IsExtern else ' | t.CExport'
|
||||
Edits.append((InsAt[0], InsAt[1], InsAt[1], Marker, ''))
|
||||
if IsStatic:
|
||||
# 编辑 2(static):存储类标记**前置**在类型左侧(联合最左)。
|
||||
# 与 TransPyV `_ParseStaticModified` / `pending_static` 通道
|
||||
# 逐字同形:`static 名字: T` → `名字: t.CStatic | T`,产出与
|
||||
# 手写 `名字: t.CStatic | T` / `@t.CStatic` 逐字段同形。
|
||||
InsAt: tuple[int, int] = Tokens[TypeStart].start
|
||||
Edits.append((InsAt[0], InsAt[1], InsAt[1], 't.CStatic | ', ''))
|
||||
else:
|
||||
# 编辑 2(export/extern):存储类标记**追加**在注解类型终点
|
||||
# (右侧):export → `| t.CExport`;extern → `| t.State`。
|
||||
InsAt = Tokens[TypeEnd - 1].end
|
||||
Marker: str = ' | t.State' if IsExtern else ' | t.CExport'
|
||||
Edits.append((InsAt[0], InsAt[1], InsAt[1], Marker, ''))
|
||||
i = TypeEnd
|
||||
continue
|
||||
i += 1
|
||||
@@ -1016,11 +1089,16 @@ def _ExpandAttributeDescriptors(Code: str) -> str:
|
||||
|
||||
|
||||
def _ExpandTypeDescriptors(Code: str) -> str:
|
||||
"""把 `const T` / `volatile T` / `static T`(含组合、任意顺序)展开为 `t.CConst | T` 等形态(行号不变)。
|
||||
"""把 `const T` / `volatile T`(含组合、任意顺序)展开为 `t.CConst | T` 等形态(行号不变)。
|
||||
|
||||
- 词法级切分(`tokenize`):注释/字符串内容天然不参与,不会被误改写。
|
||||
- 只在"注解位置"(前一个 token 是 `:` 且再前一个是 Name,或前一个 token 是 `->`)
|
||||
识别描述符串;非类型位置原样保留为普通标识符(软关键字边界)。
|
||||
- **`static` 不再属于本展开器**(已迁出注解位置):注解位置出现 `static`
|
||||
(如 `memory_regions: static memory_region* = None`)一律**响亮失败**
|
||||
(_StaticPositionSyntaxError);前置形式 `static 名字: 类型 = 值` 由
|
||||
_ExpandExportExternVar 处理,`static def` 由 vast.Parser._ParseStaticDef 处理。
|
||||
入口的 `'static' not in Code` 判据保留,仅为让上述旧位置能被扫描到并报错。
|
||||
- 只做**同行**替换(不增删换行 ⇒ 行号映射保持有效,与 fn/enum/define/typedef 同约定)。
|
||||
- 词法失败(未闭合字符串等)时原样返回:该输入在后续 ast.parse 处必然响亮失败,
|
||||
本层不新增第二套错误通道(不静默丢描述符:词法都没过,描述符根本没被识别为描述符)。
|
||||
@@ -1039,6 +1117,15 @@ def _ExpandTypeDescriptors(Code: str) -> str:
|
||||
i: int = 0
|
||||
while i < n:
|
||||
Tok = Tokens[i]
|
||||
# 旧的注解位置 static(`名字: static 类型`):已迁移为**前置**形式,此处
|
||||
# 响亮失败(不脱糖、不静默)。注意 `static 名字: 类型` / `static def 名字`
|
||||
# 的 static 位于**语句起始**、不在注解位置,故不会被本判据命中(交由
|
||||
# _ExpandExportExternVar / vast.Parser._ParseStaticDef 处理)。
|
||||
if (Tok.type == tokenize.NAME and Tok.string == 'static'
|
||||
and _InStaticOldAnnotationPosition(Tokens, i)):
|
||||
raise _StaticPositionSyntaxError(
|
||||
Tok.start[0], Tok.start[1],
|
||||
Code.splitlines()[Tok.start[0] - 1])
|
||||
if Tok.type == tokenize.NAME and Tok.string in _TYPE_DESCRIPTOR_MARKERS:
|
||||
Run: list = []
|
||||
j: int = i
|
||||
@@ -1441,7 +1528,8 @@ def ExpandSoftKeywords(Code: str) -> str:
|
||||
5) 类型描述符 `const T` / `volatile T` → `t.CConst | T` / `t.CVolatile | T`:
|
||||
与手写 `t.CConst | T` 产出**同一 AST/同一解析路径**(见 _ExpandTypeDescriptors)。
|
||||
只在注解位置生效的软关键字(`t.attr.const()` 等非类型位置原样保留);
|
||||
缺类型 / 后随非类型 / 裸用**响亮失败**(SyntaxError)。
|
||||
缺类型 / 后随非类型 / 裸用**响亮失败**(SyntaxError)。`static` 已从注解位置
|
||||
迁出——注解位置出现 `static`(`名字: static 类型`)**响亮失败**。
|
||||
6) `union NAME:` → `class NAME(t.CUnion):`:与手写 `class NAME(t.CUnion):` 产出
|
||||
**同一 AST/同一注册路径**(见 _ExpandUnionBlocks)。成员为普通注解字段。
|
||||
行首 `union` 的非 `union 名字:` 形态**响亮失败**(该词不在任何源码中作标识符)。
|
||||
@@ -1454,9 +1542,12 @@ def ExpandSoftKeywords(Code: str) -> str:
|
||||
`class 变体:` + 无载荷赋值)。行首 `renum` 的非 `renum 名字:` 形态**响亮失败**
|
||||
(该词不在任何源码中作标识符)。
|
||||
9) `export 名字: T [= 初值]` → `名字: T | t.CExport [= 初值]`;
|
||||
`extern 名字: T` → `名字: T | t.State`(见 _ExpandExportExternVar)。
|
||||
与 TPV `_parse_export_extern_var` 同一标记、同一消费路径;函数形态
|
||||
(`export def f()` / `export f()` / `extern def f()`)不受影响;
|
||||
`extern 名字: T` → `名字: T | t.State`;`static 名字: T [= 初值]` →
|
||||
`名字: t.CStatic | T [= 初值]`(见 _ExpandExportExternVar)。
|
||||
与 TPV 同一标记、同一消费路径;export/extern 在类型右侧追加标记,static 在
|
||||
类型左侧前置标记(与 TPV `_ParseStaticModified` 的 `pending_static` 同源);
|
||||
函数形态(`export def f()` / `export f()` / `extern def f()` / `static def f()`,
|
||||
后者由 vast.Parser._ParseStaticDef 处理)不受影响;
|
||||
`extern` 带初值**响亮失败**(外部定义不写初值)。
|
||||
九种展开都同行替换(长度可增,不增删换行),AST 行号映射保持有效。
|
||||
"""
|
||||
@@ -1493,19 +1584,21 @@ def _ExpandSoftKeywordsImpl(Code: str) -> str:
|
||||
# 且它自身产出的 `t.attr.X |` 不会干扰紧随的 const/volatile 展开。
|
||||
if _ATTRIBUTE_CALLEE in Code:
|
||||
Code = _ExpandAttributeDescriptors(Code)
|
||||
# static 与 const/volatile 同为注解位置的存储类描述符(`名字: static uint32 = 0`,
|
||||
# ViperOS 驱动广泛使用);三者共用同一展开器与同一 marker 表。
|
||||
# const/volatile 是注解位置的存储类描述符;`static` 已从注解位置迁出为**前置**
|
||||
# 修饰符(`static 名字: 类型 = 值`),本层进入 _ExpandTypeDescriptors 只为让旧位置
|
||||
# `名字: static 类型` 能被扫描到并**响亮失败**(见 _StaticPositionSyntaxError)。
|
||||
if 'const' in Code or 'volatile' in Code or 'static' in Code:
|
||||
Code = _ExpandTypeDescriptors(Code)
|
||||
# 裸 `[N]T` 数组前缀在描述符之后:`const [N]T` 已由 _ExpandTypeDescriptors 消化为
|
||||
# `t.CConst | t.CArray[T, N]`(此处不再有注解位置的裸 '['),避免两条路径重复改写。
|
||||
if '[' in Code:
|
||||
Code = _ExpandArrayPrefixAnnotations(Code)
|
||||
# export / extern 变量声明(语句级软关键字):必须排在**最后**——此时注解已由
|
||||
# 数组前缀 / 描述符两层脱糖成规范形态(`t.CArray[T, N]` / `t.CConst | ...`),
|
||||
# 本层只删修饰符 + 在注解类型终点插入存储类标记(`| t.CExport` / `| t.State`)。
|
||||
# 顺序若反过来,`|` 会被数组前缀展开并进元素类型(见 _ExpandExportExternVar)。
|
||||
if 'export' in Code or 'extern' in Code:
|
||||
# export / extern / static 变量声明(语句级软关键字):必须排在**最后**——此时注解
|
||||
# 已由数组前缀 / 描述符两层脱糖成规范形态(`t.CArray[T, N]` / `t.CConst | ...`),
|
||||
# 本层只删修饰符 + 插入存储类标记(export/extern 右追加 `| t.CExport` / `| t.State`;
|
||||
# static 左前置 `t.CStatic | `)。顺序若反过来,`|` 会被数组前缀展开并进元素类型
|
||||
# (见 _ExpandExportExternVar)。
|
||||
if 'export' in Code or 'extern' in Code or 'static' in Code:
|
||||
Code = _ExpandExportExternVar(Code)
|
||||
return Code
|
||||
|
||||
|
||||
@@ -108,6 +108,14 @@ class Parser(ExprParserMixin):
|
||||
# 必须在软关键字 def 分派之前
|
||||
if v == 'export':
|
||||
return self._ParseExportDef()
|
||||
# static 存储类软关键字(已从"注解位置"迁出为**语句起始前置**修饰符):
|
||||
# 仅 `static def 名字` 形态判定为函数定义——判据必须同时要求第二个 token
|
||||
# 是 `def`,故 `static = 5` / `static x = 5` 不会被误吃成函数定义。
|
||||
# 变量形式 `static 名字: 类型 = 值` 不在本层处理,由 SymbolUtils 的前置
|
||||
# 修饰符展开统一脱糖为 `名字: t.CStatic | 类型 = 值`。
|
||||
if (v == 'static' and self._Peek(1).Type == NAME
|
||||
and self._Peek(1).Value == 'def'):
|
||||
return self._ParseStaticDef()
|
||||
# define 宏函数定义(与 def 语义一致,返回注解自动追加 t.CDefine
|
||||
# 标记为宏函数;软关键字:仅"define + 标识符"形态才判定为函数定义,
|
||||
# 变量名/调用(define = 5、define(x))不受影响)——必须在软关键字
|
||||
@@ -565,6 +573,9 @@ class Parser(ExprParserMixin):
|
||||
return self._ParseExternDef(decorators=decorator_list)
|
||||
if tok.Type == NAME and tok.Value == 'export':
|
||||
return self._ParseExportDef(decorators=decorator_list)
|
||||
if (tok.Type == NAME and tok.Value == 'static' and self._Peek(1).Type == NAME
|
||||
and self._Peek(1).Value == 'def'):
|
||||
return self._ParseStaticDef(decorators=decorator_list)
|
||||
if tok.Type == NAME and tok.Value == 'define':
|
||||
return self._ParseDefineDef(decorators=decorator_list)
|
||||
if tok.Type == NAME and tok.Value == 'def':
|
||||
@@ -772,6 +783,63 @@ class Parser(ExprParserMixin):
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
def _ParseStaticDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
|
||||
"""解析 static 函数定义(等价 ``@t.CStatic``,与 TransPyV 的
|
||||
`_ParseStaticModified` 同源)。
|
||||
|
||||
允许语法(与 export/extern 对称,配不配 def 都一样):
|
||||
static def A(x: int) -> int: ...
|
||||
static A(x: int) -> int: ...
|
||||
|
||||
与 export/extern 的**两处不同**:
|
||||
- **不改写返回注解**(不追加 `| t.CStatic` / `| t.State`):CStatic 是
|
||||
函数属性,由下面的合成装饰器承载,返回类型语义逐字不变;
|
||||
- **合成 `@t.CStatic` 装饰器**追加在既有装饰器之后,产出与**手写
|
||||
`@t.CStatic`** 逐字段同形(decorator_list 多一个
|
||||
Attribute(Name('t', Load), 'CStatic', Load)),下游零新增判据。
|
||||
|
||||
另设自定义属性 ``Static = True`` 供 Unparser 还原 static 语法
|
||||
(镜像 Extern/Export;因 FunctionDef 的 __slots__ 槽位未含 Static 且
|
||||
补槽位需改第三个文件,此处仅在槽位存在时设置,解析不会因此中断)。
|
||||
"""
|
||||
start: Token = self._Next() # 'static'
|
||||
if self._AtName('def'):
|
||||
self._Next()
|
||||
name_tok: Token = self._ExpectName()
|
||||
type_params: list[N.AST] = []
|
||||
if self._AtOp('['):
|
||||
type_params = self._ParseTypeParams()
|
||||
args: N.arguments = self._ParseArguments()
|
||||
returns: N.expr | None = None
|
||||
if self._AtOp('->'):
|
||||
self._Next()
|
||||
returns = self._ParseTypeAnnotation()
|
||||
body: list[N.stmt] = []
|
||||
if self._AtOp(':'):
|
||||
self._Next()
|
||||
body = self._ParseSuite()
|
||||
# 合成 @t.CStatic 装饰器(追加在既有装饰器之后)
|
||||
static_attr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()),
|
||||
attr='CStatic', ctx=N.Load())
|
||||
self._FixLoc(static_attr, start)
|
||||
deco_list: list[N.expr] = list(decorators or [])
|
||||
deco_list.append(static_attr)
|
||||
node: N.FunctionDef = N.FunctionDef(
|
||||
name=name_tok.Value, args=args, body=body,
|
||||
decorator_list=deco_list, returns=returns,
|
||||
type_comment=None, type_params=type_params,
|
||||
)
|
||||
# 自定义属性 Static = True 供 Unparser 还原 static 语法(镜像 Extern/Export)。
|
||||
# 注:FunctionDef 是 __slots__ 类(见 vast/Nodes.py 的 _FUNC_ATTRS,当前槽位
|
||||
# 为 Extern/Export/Define,未含 Static)——补槽位需改第三个文件(本次不许可),
|
||||
# 故仅在槽位存在时设置,避免 AttributeError 中断解析;下游对 static 函数的
|
||||
# 识别靠上面合成的 @t.CStatic 装饰器(HandlesFunctions 的存储类装饰器分支),
|
||||
# 与 virtual/novirtual 仅合成装饰器同构。
|
||||
if hasattr(type(node), 'Static'):
|
||||
node.Static = True
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
def _ParseDefineDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
|
||||
"""解析 define 宏函数定义(语法与 def 完全一致,但固定为宏函数)。
|
||||
|
||||
|
||||
Reference in new issue
Block a user