From d2f66811fbec977b92aff666315cedd77a8c8fc9 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 22 Sep 2026 21:26:16 +0800 Subject: [PATCH] =?UTF-8?q?refactor(vipeye-internal):=20str/bytes=20?= =?UTF-8?q?=E4=B8=8B=E6=A0=87=E7=BB=9F=E4=B8=80=E8=BF=94=E5=9B=9E=20char?= =?UTF-8?q?=EF=BC=88=E4=B8=8E=20*s=20=E8=A7=A3=E5=BC=95=E7=94=A8=E4=B8=80?= =?UTF-8?q?=E8=87=B4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `s[i]` 原返回 t.CChar,而 `*s` 返回 char,同一 i8 元素出现两种显示。现把 str/bytes 的下标通路(普通下标 + TypeSet 下标)统一改为内置 char 对象,二者本就可隐式互转。 迭代(for ch in s)与 Iterable 实参推断仍保持 t.CChar,待确认是否一并统一。 回归用例:viperUnaryPointer.test.ts 中 fmt[0] 断言改为 char。 版本号提升至 1.1.421 并更新 CHANGELOG。 --- packages/vipeye-internal/package-lock.json | 4 +-- packages/vipeye-internal/package.json | 2 +- .../src/analyzer/typeEvaluator.ts | 26 +++++-------------- .../src/tests/viperUnaryPointer.test.ts | 7 ++--- packages/vipeye/package-lock.json | 4 +-- packages/vipeye/package.json | 2 +- packages/vscode-vipeye/CHANGELOG.md | 6 ++++- packages/vscode-vipeye/package-lock.json | 4 +-- packages/vscode-vipeye/package.json | 4 +-- 9 files changed, 24 insertions(+), 35 deletions(-) diff --git a/packages/vipeye-internal/package-lock.json b/packages/vipeye-internal/package-lock.json index 82058824..2f48c444 100644 --- a/packages/vipeye-internal/package-lock.json +++ b/packages/vipeye-internal/package-lock.json @@ -1,12 +1,12 @@ { "name": "vipeye-internal", - "version": "1.1.420", + "version": "1.1.421", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vipeye-internal", - "version": "1.1.420", + "version": "1.1.421", "license": "MIT", "dependencies": { "@yarnpkg/fslib": "2.10.4", diff --git a/packages/vipeye-internal/package.json b/packages/vipeye-internal/package.json index 5e7d2279..27cf6a7a 100644 --- a/packages/vipeye-internal/package.json +++ b/packages/vipeye-internal/package.json @@ -2,7 +2,7 @@ "name": "vipeye-internal", "displayName": "vipeye", "description": "Type checker for the Viper language", - "version": "1.1.420", + "version": "1.1.421", "license": "MIT", "private": true, "files": [ diff --git a/packages/vipeye-internal/src/analyzer/typeEvaluator.ts b/packages/vipeye-internal/src/analyzer/typeEvaluator.ts index 525b8f43..4322824e 100644 --- a/packages/vipeye-internal/src/analyzer/typeEvaluator.ts +++ b/packages/vipeye-internal/src/analyzer/typeEvaluator.ts @@ -8412,17 +8412,9 @@ export function createTypeEvaluator( if (isClassInstance(concreteSubtype)) { // Viper TypeSet:str/bytes 在类型组合中表示 C 字符串指针(i8*), - // 下标访问 a[i] 应返回 t.CChar(int 别名),而非 str/bytes。 - if ( - isViperTypeSetIndex && - ClassType.isBuiltIn(concreteSubtype, ['str', 'bytes']) - ) { - // 构造带 CChar 别名信息的 int 类型(保留 t.CChar 显示信息) - const ccharType = getViperCCharType(node); - if (ccharType) { - return ccharType; - } - return concreteSubtype; + // 下标访问 a[i] 应返回 char(i8 字符),而非 str/bytes。 + if (isViperTypeSetIndex && ClassType.isBuiltIn(concreteSubtype, ['str', 'bytes'])) { + return getBuiltInObject(node, 'char'); } // Viper TypeSet:非修饰基本类型(int/float/bool 等)在类型组合中 // 表示指针指向的目标类型(如 CConst | int | CPtr = const int*), @@ -8435,20 +8427,16 @@ export function createTypeEvaluator( ) { return concreteSubtype; } - // Viper 扩展:str/bytes 表示 C 字符串指针(i8* / i8*)。 + // Viper 扩展:str/bytes 表示 C 字符串指针(i8*)。 // 无论读写,下标访问 a[i] 都是指针解引用操作(C 语义): - // - 读取 a[i] 返回 t.CChar(i8 字节),而非 Python str.__getitem__ 的 str + // - 读取 a[i] 返回 char(i8 字节),与解引用 `*a` 的结果类型一致, + // 而非 Python str.__getitem__ 的 str // - 赋值 a[i] = v 是合法的指针写字节操作,不报 __setitem__ 不存在 if ( IsViperDialect(viperIndexFileInfo.executionEnvironment.dialect) && ClassType.isBuiltIn(concreteSubtype, ['str', 'bytes']) ) { - // 构造带 CChar 别名信息的 int 类型作为下标访问的目标类型 - const ccharType = getViperCCharType(node); - if (ccharType) { - return ccharType; - } - return concreteSubtype; + return getBuiltInObject(node, 'char'); } const typeResult = getTypeOfIndexedObjectOrClass(node, concreteSubtype, selfType, usage); if (typeResult.isIncomplete) { diff --git a/packages/vipeye-internal/src/tests/viperUnaryPointer.test.ts b/packages/vipeye-internal/src/tests/viperUnaryPointer.test.ts index 7b7e5400..ae5bd82a 100644 --- a/packages/vipeye-internal/src/tests/viperUnaryPointer.test.ts +++ b/packages/vipeye-internal/src/tests/viperUnaryPointer.test.ts @@ -587,13 +587,10 @@ def test_str_arith(fmt: str) -> int: assert.strictEqual(op.type, 'str', `指针算术结果应为 str (L${line}),实际: ${op.type}`); } - // L7:fmt[0] → t.CChar(C 的 char 字节;与 `*fmt` 的 char 可隐式互转) + // L7:fmt[0] → char(与 `*fmt` 解引用统一为同一元素类型) const subscript = indexTypes.find((i) => i.line === 7); assert(subscript, `下标访问未找到 (L7)`); - assert( - subscript.type.includes('CChar'), - `fmt[0] 应为 t.CChar,实际: ${subscript.type}` - ); + assert.strictEqual(subscript.type, 'char', `fmt[0] 应为 char,实际: ${subscript.type}`); const diagnostics = getDiagnostics(program, configOptions, uri); console.log('=== 诊断 ==='); diagnostics.forEach((d) => console.log(` ${d}`)); diff --git a/packages/vipeye/package-lock.json b/packages/vipeye/package-lock.json index 62d20835..f0f65db4 100644 --- a/packages/vipeye/package-lock.json +++ b/packages/vipeye/package-lock.json @@ -1,12 +1,12 @@ { "name": "vipeye", - "version": "1.1.420", + "version": "1.1.421", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vipeye", - "version": "1.1.420", + "version": "1.1.421", "license": "MIT", "bin": { "vipeye": "index.js", diff --git a/packages/vipeye/package.json b/packages/vipeye/package.json index da5631fd..c5b6b46a 100644 --- a/packages/vipeye/package.json +++ b/packages/vipeye/package.json @@ -2,7 +2,7 @@ "name": "vipeye", "displayName": "Vipeye", "description": "Type checker for the Viper language", - "version": "1.1.420", + "version": "1.1.421", "license": "MIT", "author": { "name": "TermiNexus" diff --git a/packages/vscode-vipeye/CHANGELOG.md b/packages/vscode-vipeye/CHANGELOG.md index 567ff97b..f2356282 100644 --- a/packages/vscode-vipeye/CHANGELOG.md +++ b/packages/vscode-vipeye/CHANGELOG.md @@ -1,8 +1,12 @@ # Change Log +## 1.1.421 + +- `s[i]` on `str` / `bytes` now yields `char` (`i8`) instead of `t.CChar`, matching the dereference result of `*s` (the two remain implicitly convertible). Covers both the plain subscript path and the type-set subscript path (e.g. `CConst | str | CPtr` style annotations); iteration (`for ch in s`) and `Iterable` argument inference still produce `t.CChar` + ## 1.1.420 -- Pointer semantics for `str` / `bytes` (both are C `char*`, `i8*`) now cover pointer arithmetic and writes, matching the dereference support added earlier: `p + n`, `p - n` and `n + p` return the pointer type instead of reporting `reportOperatorIssue`, and `*p = v` is accepted as an assignment target. `p[i]` already yielded `t.CChar` and is unchanged +- Pointer semantics for `str` / `bytes` (both are C `char*`, `i8*`) now cover pointer arithmetic and writes, matching the dereference support added earlier: `p + n`, `p - n` and `n + p` return the pointer type instead of reporting `reportOperatorIssue`, and `*p = v` is accepted as an assignment target. Subscript access `p[i]` was already supported - Built-in C basic type names extended with `short` (`t.CShort`), `ushort` (`t.CUnsignedShort`), `ulong` (`t.CUnsignedLong`) and `ulonglong` (`t.CUnsignedLongLong`), alongside the existing `long` / `longlong` ## 1.1.419 diff --git a/packages/vscode-vipeye/package-lock.json b/packages/vscode-vipeye/package-lock.json index 0083fecb..e4121e3f 100644 --- a/packages/vscode-vipeye/package-lock.json +++ b/packages/vscode-vipeye/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-vipeye", - "version": "1.1.420", + "version": "1.1.421", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-vipeye", - "version": "1.1.420", + "version": "1.1.421", "license": "MIT", "dependencies": { "mermaid": "^11.12.0", diff --git a/packages/vscode-vipeye/package.json b/packages/vscode-vipeye/package.json index 2f727a11..477ad657 100644 --- a/packages/vscode-vipeye/package.json +++ b/packages/vscode-vipeye/package.json @@ -1,8 +1,8 @@ { - "name": "vscode-vipeye", + "name": "vipeye", "displayName": "Vipeye", "description": "VS Code language support for Viper (LSP client)", - "version": "1.1.420", + "version": "1.1.421", "private": true, "license": "MIT", "author": {