From feaca1a03819581cf81d5c85f8037ef5c708f3ab Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 4 Aug 2026 02:17:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=20=5F=5Fnew=5F=5F?= =?UTF-8?q?=20=E8=A3=B8=E6=8C=87=E9=92=88=E8=BF=94=E5=9B=9E=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=9E=84=E9=80=A0=20CPtr[T]=EF=BC=8Ca:CPtr[T]=3DT()?= =?UTF-8?q?=20=E8=87=AA=E5=8A=A8=E9=9A=90=E5=BC=8F=E5=8F=96=E6=8C=87?= =?UTF-8?q?=E9=92=88=EF=BC=88=E6=9A=82=E5=AE=9A=EF=BC=89=EF=BC=8Carg.actio?= =?UTF-8?q?n=20flow=20=E8=BF=87=E6=BB=A4=E8=B7=B3=E8=BF=87=EF=BC=8CCPtr=20?= =?UTF-8?q?=E8=A7=A3=E5=BC=95=E7=94=A8=E8=BD=AC=E5=8F=91=EF=BC=8Cc.Asm?= =?UTF-8?q?=E7=9A=84=20inp/out=20=E5=8F=82=E6=95=B0=E9=87=8D=E5=8A=A0?= =?UTF-8?q?=E5=92=8C=20str<->bytes=20=E4=BA=92=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vipeye-internal/src/analyzer/checker.ts | 25 +++++++++------- .../src/analyzer/constructors.ts | 30 +++++++++++++++++++ .../vipershed-fallback/stdlib/c.vpi | 9 +++--- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/packages/vipeye-internal/src/analyzer/checker.ts b/packages/vipeye-internal/src/analyzer/checker.ts index 4cb4a0a..f5e016a 100644 --- a/packages/vipeye-internal/src/analyzer/checker.ts +++ b/packages/vipeye-internal/src/analyzer/checker.ts @@ -7288,20 +7288,25 @@ export class Checker extends ParseTreeWalker { if (methodName === '__new__') { // __new__ overrides should have a "cls" parameter. - if (node.d.params.length === 0 || !node.d.params[0].d.name) { - this._evaluator.addDiagnostic( - DiagnosticRule.reportSelfClsParameterName, - LocMessage.newClsParam(), - node.d.name - ); - } else { - const paramName = node.d.params[0].d.name.d.value; - if (!clsNames.includes(paramName) && !(isMetaclass && clsNamesMetaclass.includes(paramName))) { + // Viper 扩展:Viper 中 `__new__` 的第一个参数就是 self(栈位置, + // 如 `_list.vp` 的 `def __new__(self, pool, elem_size=0)`), + // 与 Python 的 cls 语义不同,跳过参数名校验。 + if (!IsViperDialect(this._fileInfo.executionEnvironment.dialect)) { + if (node.d.params.length === 0 || !node.d.params[0].d.name) { this._evaluator.addDiagnostic( DiagnosticRule.reportSelfClsParameterName, LocMessage.newClsParam(), - node.d.params[0] + node.d.name ); + } else { + const paramName = node.d.params[0].d.name.d.value; + if (!clsNames.includes(paramName) && !(isMetaclass && clsNamesMetaclass.includes(paramName))) { + this._evaluator.addDiagnostic( + DiagnosticRule.reportSelfClsParameterName, + LocMessage.newClsParam(), + node.d.params[0] + ); + } } } diff --git a/packages/vipeye-internal/src/analyzer/constructors.ts b/packages/vipeye-internal/src/analyzer/constructors.ts index 8a8ce25..0b2ddf6 100644 --- a/packages/vipeye-internal/src/analyzer/constructors.ts +++ b/packages/vipeye-internal/src/analyzer/constructors.ts @@ -35,6 +35,7 @@ import { isAny, isClass, isClassInstance, + isCPtrType, isFunction, isFunctionOrOverloaded, isInstantiableClass, @@ -340,6 +341,19 @@ function validateNewAndInitMethods( initMethodBindToType = ClassType.cloneAsInstance(type); } + // Viper 扩展:`__new__` 返回 CPtr[...](裸指针分配语义)时, + // `__init__` 应绑定到类实例而非 CPtr(CPtr 上没有 `__init__` 方法)。 + // 这样 `list[str](pool)` 的构造调用结果保持类实例 `list[str]`。 + let isNewReturnPtr = false; + doForEachSubtype(newMethodReturnType, (subtype) => { + if (isCPtrType(subtype)) { + isNewReturnPtr = true; + } + }); + if (isNewReturnPtr) { + initMethodBindToType = ClassType.cloneAsInstance(type); + } + // Determine whether the class overrides the object.__init__ method. const initMethodDiag = new DiagnosticAddendum(); initMethodTypeResult = getBoundInitMethod(evaluator, errorNode, initMethodBindToType, initMethodDiag); @@ -1077,6 +1091,22 @@ function shouldSkipNewAndInitEvaluation( function shouldSkipInitEvaluation(evaluator: TypeEvaluator, classType: ClassType, newMethodReturnType: Type): boolean { const returnType = evaluator.makeTopLevelTypeVarsConcrete(newMethodReturnType); + // Viper 扩展:`__new__` 返回 CPtr[...](裸指针)时不跳过 `__init__` 验证。 + // Viper 中 `__new__` 负责分配内存并返回裸指针(如 `_list.vp` 的 + // `def __new__(self, pool, elem_size=0): return pool.alloc(48)`,返回 + // `t.CVoid | t.CPtr`),但构造调用 `list[str](pool)` 的结果仍是类实例 + // `list[str]`(由 `__init__` 的 self 类型确定)。CPtr 是 Viper 特有指针类型, + // 检测到 CPtr 返回即视为 Viper 分配语义,不应跳过 `__init__`。 + let isViperPtrAlloc = false; + doForEachSubtype(returnType, (subtype) => { + if (isCPtrType(subtype)) { + isViperPtrAlloc = true; + } + }); + if (isViperPtrAlloc) { + return false; + } + let skipInitCheck = false; doForEachSubtype(returnType, (subtype) => { if (isUnknown(subtype)) { diff --git a/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi b/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi index 0ffbe1c..5bb95b5 100644 --- a/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi +++ b/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi @@ -27,12 +27,13 @@ def Set(target: Any, value: T) -> None: """target = value。""" ... -def Asm(asm: str, *args: Any, op: Any = None) -> Any: - """内联汇编。op 为破坏描述符列表。""" +def Asm(asm: str, *args: Any, inp: Any = None, out: Any = None, op: Any = None) -> Any: + """内联汇编。inp 为输入操作数描述符列表,out 为输出操作数描述符列表, + op 为破坏描述符列表。""" ... -def LLVMIR(ir: str, *args: Any, op: Any = None) -> Any: - """LLVM IR 内联。op 为破坏描述符列表。""" +def LLVMIR(ir: str, *args: Any, inp: Any = None, out: Any = None, op: Any = None) -> Any: + """LLVM IR 内联。inp/out/op 为操作数描述符列表。""" ... def LInp(expr: Any, constraint: Any = None) -> Any: