fix(vipeye-internal): str/bytes 支持一元 '*' 解引用,结果为 char
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
Viper 里 str 与 bytes 都是 C 的 char*(i8*),`*s` 应取首字符且类型为 char(i8); 此前被当成非指针类型处理,报「类型 "str" 不支持运算符 "*"」(reportOperatorIssue)。 在 getTypeOfViperDeref 中把 str/bytes 与已有的 CPtr[X] 分支并列处理。 回归用例:viperUnaryPointer.test.ts 新增 *fmt(str)与 *buf(bytes)→ char, 并断言不报运算符错误。版本号提升至 1.1.419 并更新 CHANGELOG。
This commit is contained in:
1 parent
4bc462e0f3
commit
00b781a5cc
9 files changed
+81
-9
No files matched your search
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "vipeye-internal",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vipeye-internal",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"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.418",
|
||||
"version": "1.1.419",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"files": [
|
||||
|
||||
@@ -850,6 +850,7 @@ export function getTypeOfUnaryOperation(
|
||||
|
||||
// Viper 扩展:一元 '*'(解引用)类型求值,与 C 语义一致。
|
||||
// - CPtr[X](含 `X | t.CPtr` 化简形式)→ 返回目标类型 X(类对象转为实例)
|
||||
// - str / bytes(C 的 char*,即 i8*)→ 返回 char(i8)
|
||||
// - Unknown/Any → 透传
|
||||
// - 非指针类型 → 报错(C 语义:invalid type argument of unary '*')
|
||||
function getTypeOfViperDeref(
|
||||
@@ -867,6 +868,12 @@ function getTypeOfViperDeref(
|
||||
return subtype;
|
||||
}
|
||||
|
||||
// Viper:str / bytes 都是 C 的 char*(i8*),解引用取首字符,类型为 char(i8)。
|
||||
if (isClassInstance(subtype) && ClassType.isBuiltIn(subtype, ['str', 'bytes'])) {
|
||||
resultTypes.push(evaluator.getBuiltInObject(node, 'char'));
|
||||
return subtype;
|
||||
}
|
||||
|
||||
if (isClassInstance(subtype) && isCPtrType(subtype)) {
|
||||
const typeArgs = subtype.priv.typeArgs;
|
||||
if (typeArgs && typeArgs.length > 0) {
|
||||
|
||||
@@ -458,3 +458,64 @@ def main() -> int:
|
||||
program.dispose();
|
||||
serviceProvider.dispose();
|
||||
});
|
||||
|
||||
// Viper:str / bytes 都是 C 的 char*(i8*),`*s` 取首字符,类型为 char(i8)。
|
||||
// 修复「类型 "str" 不支持运算符 "*"」(reportOperatorIssue)。
|
||||
test('Viper 解引用 str/bytes 返回 char', () => {
|
||||
const code = `import t
|
||||
|
||||
def test_str_deref(fmt: str) -> int:
|
||||
c: char = *fmt
|
||||
return 0
|
||||
|
||||
def test_bytes_deref(buf: bytes) -> int:
|
||||
ch: char = *buf
|
||||
return 0
|
||||
`;
|
||||
const { program, configOptions, parseResults, uri, serviceProvider } = buildProgramForCode(code);
|
||||
|
||||
const evaluator = program.evaluator as TypeEvaluator | undefined;
|
||||
assert(evaluator, 'evaluator not available');
|
||||
const ev = evaluator;
|
||||
|
||||
const derefs: { line: number; type: string }[] = [];
|
||||
class UnaryCollector extends ParseTreeWalker {
|
||||
override visitUnaryOperation(node: UnaryOperationNode) {
|
||||
if (node.d.operator !== OperatorType.Multiply) {
|
||||
return true;
|
||||
}
|
||||
const type = ev.getType(node as any);
|
||||
derefs.push({
|
||||
line: convertOffsetToPosition(node.start, parseResults.parserOutput.lines).line + 1,
|
||||
type: type ? program.printType(type) : '(undefined)',
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
new UnaryCollector().walk(parseResults.parserOutput.parseTree);
|
||||
|
||||
console.log('=== str/bytes 解引用类型 ===');
|
||||
derefs.forEach((d) => console.log(` L${d.line}: ${d.type}`));
|
||||
|
||||
// L4: *fmt(fmt: str,即 i8*)→ char
|
||||
const strDeref = derefs.find((d) => d.line === 4);
|
||||
assert(strDeref, '*fmt not found (L4)');
|
||||
assert.strictEqual(strDeref.type, 'char', `*fmt 应为 char,实际: ${strDeref.type}`);
|
||||
|
||||
// L8: *buf(buf: bytes,即 i8*)→ char
|
||||
const bytesDeref = derefs.find((d) => d.line === 8);
|
||||
assert(bytesDeref, '*buf not found (L8)');
|
||||
assert.strictEqual(bytesDeref.type, 'char', `*buf 应为 char,实际: ${bytesDeref.type}`);
|
||||
|
||||
// 不得报「类型 "str" / "bytes" 不支持运算符 "*"」
|
||||
const diagnostics = getDiagnostics(program, configOptions, uri);
|
||||
console.log('=== 诊断 ===');
|
||||
diagnostics.forEach((d) => console.log(` ${d}`));
|
||||
assert(
|
||||
!diagnostics.some((d) => d.includes('不支持运算符')),
|
||||
`str/bytes 解引用不应报运算符错误: ${JSON.stringify(diagnostics)}`
|
||||
);
|
||||
|
||||
program.dispose();
|
||||
serviceProvider.dispose();
|
||||
});
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "vipeye",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vipeye",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"vipeye": "index.js",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "vipeye",
|
||||
"displayName": "Vipeye",
|
||||
"description": "Type checker for the Viper language",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "TermiNexus"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Change Log
|
||||
|
||||
## 1.1.419
|
||||
|
||||
- Dereferencing `str` / `bytes` with the unary `*` operator no longer reports `reportOperatorIssue`: both are C `char*` (`i8*`) in Viper, so `*s` yields `char` (`i8`). Mirrors `t.CPtr[X]` dereferencing, which already returned the pointee type
|
||||
|
||||
## 1.1.418
|
||||
|
||||
- **Built-in C basic type names**: `long` (`t.CLong`) and `longlong` (`t.CLongLong`) are now built-in typedefs, mirroring the compiler's `_CNAME_ALIAS` table (`char`, `short`, `long`, `unsigned` and friends are language built-ins that need no import). C's `long long` cannot be spelled with a space, so Viper writes `longlong`; the unsigned form stays available as `t.CUnsignedLongLong`
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "vscode-vipeye",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vscode-vipeye",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mermaid": "^11.12.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "vscode-vipeye",
|
||||
"displayName": "Vipeye",
|
||||
"description": "VS Code language support for Viper (LSP client)",
|
||||
"version": "1.1.418",
|
||||
"version": "1.1.419",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
|
||||
Reference in new issue
Block a user