From 68e5299139d9c32f49c0df4eed615de6efa273ce Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 23 Oct 2026 23:01:43 +0800 Subject: [PATCH] =?UTF-8?q?docs(wiki):=20=E6=96=B0=E5=A2=9E=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=AD=97=E5=88=86=E5=B1=82=E4=B8=8E=E4=BF=9D=E7=95=99?= =?UTF-8?q?=E5=AD=97=E6=B8=85=E5=8D=95=EF=BC=8C=E6=A0=A1=E5=87=86=20extern?= =?UTF-8?q?=20=E5=86=85=E9=83=A8=E6=A0=87=E8=AE=B0=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - README.MD:新增「关键字分层与保留字」小节(保留字 / 上下文软关键字 / 纯词三层 + 拒绝位置) - README.MD:FFI 说明由已退役的 T | t.State 改为 State[T] / ExportT[T] - 08-c-operations.md:同步 extern/export 与 extern 全局的内部标记承载写法 --- 08-c-operations.md | 13 ++++++++----- README.MD | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/08-c-operations.md b/08-c-operations.md index 40d4565..241df94 100644 --- a/08-c-operations.md +++ b/08-c-operations.md @@ -267,7 +267,9 @@ Viper 的 FFI(Foreign Function Interface)通过 `extern` / `export` 关键 - `extern def foo() -> T`(函数体为 `pass`):仅声明。编译器只生成 `declare` 原型,不生成 `define` 函数体,由链接器在外部库中解析符号; - `export def foo() -> T`:以裸名导出函数定义。 -> `extern` / `export` 是语言层软关键字,解析器会把它们改写为返回注解中的存储类标记(`extern` → `T | t.State`,`export` → `T | t.CExport`)。`t.State` / `t.CExtern` / `t.CExport` 标记并未废弃,仍是这些关键字与 `extern` 全局变量的内部承载。 +> `extern` / `export` 是语言层软关键字,解析器会把它们改写为返回注解中的存储类标记包装(`extern` → `State[T]`,`export` → `ExportT[T]`)。`State` / `ExternT` / `ExportT` 标记仍是这些关键字与 `extern` 全局变量的内部承载。 +> +> 注意:注解中的旧联合写法 `T | t.State` 已退役(注解里不允许 `|`),现在只能用 `extern` 关键字(或内部形式 `State[T]`)。 ### 基本声明 @@ -318,19 +320,20 @@ HANDLE CreateFileA(LPCSTR, ULONG, ULONG, SECURITY_ATTRIBUTES*, | `extern def f()` | ❌ 不加 | 仅 `declare` | FFI 外部函数声明(引用外部) | | `export def f()` | ❌ 不加 | 裸名 `define` | 对外导出 API | -> 新关键字等价写法:无修饰 = 普通函数加 SHA1 前缀;`extern` = 仅 declare;`export` = 裸名 define。旧的 `t.CExtern` / `t.CExport` / `t.State` 标记在内部仍承载这些关键字,手写可用但不推荐。 +> 新关键字等价写法:无修饰 = 普通函数加 SHA1 前缀;`extern` = 仅 declare;`export` = 裸名 define。内部承载标记为 `State[T]`(extern)/ `ExportT[T]`(export);旧联合写法 `T | t.CExtern` 已不可解析。 > **`extern` 重名(临时规则,待修正)**:多个模块声明同名 `extern` 符号时,调用点按**依赖 / 导入顺序取「最近」的那个**实体;请避免多模块重复声明同名 `extern`,该行为日后会修正。详见 [10-imports.md 的跨模块约束](10-imports.md#跨模块约束)。 ### 声明外部全局变量 -外部全局变量用 `extern` 软关键字声明(推荐),或等价的 `t.CExtern` 标记: +外部全局变量用 `extern` 软关键字声明: ```python -extern errno: int # extern int errno;(推荐) -fd: t.CExtern | int # 等价写法(内部标记) +extern errno: int # extern int errno; ``` +解析器把它改写为 `errno: State[int]`(内部标记包装),后续走同一条 external global 路径。 + 模块级 `extern` 全局生成 `@裸名 = external global T`(external linkage、无初始值、无 storage),符号由外部单元提供。 详见 [02-type-system.md 的 t.State 章节](02-type-system.md#tstate-声明性标记) 和 [includes/w32](../includes/w32) 的 Win32 绑定实现。 diff --git a/README.MD b/README.MD index b0b645f..e61a526 100644 --- a/README.MD +++ b/README.MD @@ -34,6 +34,22 @@ | 空值 | `None` | `None`(编译为 `NULL`/零值) | | 模块系统 | 运行时 `import` | 编译时解析,插入 `.stub.ll`,`SHA1` 命名空间隔离 | +### 关键字分层与保留字 + +Viper 的关键字分三层,判据以 [includes/ast/tokens.vp](../includes/ast/tokens.vp) 的枚举注释为准: + +| 层级 | 词 | 规则 | +|---|---|---| +| **保留字(硬)** | `typedef` `define` `enum` `union` `renum` `struct` `switch` `fallthrough` `export` | 语句级语法,**任何标识符位置都禁用**(变量名/函数名/类名/形参名/模块别名/循环变量) | +| **上下文软关键字** | `fn` `fun` `func` `function`、`extern`、`const` `volatile` `bigend` `littlend`、`virtual` `novirtual`、`tls` | 只在特定位置生效;其它位置仍是普通标识符(例如 AST 字段 `func: AST*`) | +| **非关键字(纯词)** | `inline` `static` `cif` `celif` `celse` `default` `temp` `__attribute__` | 不进关键字表,仅由解析器按上下文识别 | + +保留字的拒绝实现在 `parser.vp::_RejectReservedIdent` / `_RejectReservedTargets`,TPC 侧同一张表在 `TransPyC/lib/vast/Tokenizer.py::RESERVED_KEYWORDS`(报错文案一致)。 + +> **两个必须知道的细节**: +> 1. 保留字在**语句首**会先被当作语法消费(`enum X:` / `switch x:` / `fallthrough`),因此 `enum = 1` 报的是语法错误;新检查覆盖的是**非语句首**的标识符位置(`def struct()`、`class union:`、`def f(switch: int)`、`import x as typedef`、`for renum in ...`、`a, enum = ...`)。 +> 2. `func` / `temp` / `default` **故意不列为保留字**:它们分别是 AST 字段名(`Call.func`)、`includes/viperlib.vp` 的局部变量名、`includes/argparse.vp` 的形参名。 + ### 与 C 的关系 Viper 编译后的代码在底层等价于 `C` 编译后的机器码(都经过 LLVM),但 Viper 在语言层面提供了 C 所没有的能力: @@ -46,7 +62,7 @@ Viper 编译后的代码在底层等价于 `C` 编译后的机器码(都经过 - **存根驱动的模块系统**:`.vpi` 存根文件实现跨模块类型解析,无需头文件 - **更多内容**:额外更多的不依赖操作系统的函数和语法 -> **FFI/导出新写法**:推荐使用语言软关键字 `extern`/`export`——`extern def foo(...) -> T` 仅声明外部函数(实现来自外部),`export def` 以裸名导出符号。解析器会把它们改写为返回注解中的存储类标记(`extern` → `T | t.State`,`export` → `t.CExport`),因此 `t.State`/`t.CExtern`/`t.CExport` 标记并未废弃,仍是内部承载(手写可用)。 +> **FFI/导出新写法**:推荐使用语言软关键字 `extern`/`export`——`extern def foo(...) -> T` 仅声明外部函数(实现来自外部),`export def` 以裸名导出符号。解析器会把它们改写为返回注解中的存储类标记包装(`extern` → `State[T]`,`export` → `ExportT[T]`),因此 `State`/`ExternT`/`ExportT` 标记仍是内部承载(手写 `State[T]` 可用)。注意 `T | t.State` 这类旧联合写法已退役:注解中不允许 `|`。 ### C-LIKE 语法(逐步支持)