refactor(vipeye-internal): str/bytes 下标统一返回 char(与 *s 解引用一致)
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
`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。
This commit is contained in:
1 parent
1aa1b1f2f0
commit
d2f66811fb
9 files changed
+24
-35
No files matched your search
+2
-2
@@ -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",
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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}`));
|
||||
|
||||
Generated
+2
-2
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
Generated
+2
-2
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in new issue
Block a user