refactor(return): 移除 @c.CReturn 多返回值处理器,只保留 -> tuple[ty1, ty2, ...],遇到 CReturn 一律报错
DeclarationGenerator:tuple[...] 分支逐字保留(仅 CReturnTypes 机械改名 MultiRetTypes),装饰器分支改为 SyntaxError,报文含函数名与“请改用 -> tuple[ty1, ty2, ...]”提示 HandlesAssign(a, b = f() 解包路径):删除装饰器收集分支并改为报错;tuple[...] 恢复与逐个解包逻辑逐字不变 HandlesFunctions:新增 _CRETURN_REMOVED_HINT 与 _RejectCReturnDecorator,在函数定义入口(_GetFunctionSignatureLlvm / _EmitFunctionLlvm)fail-fast——即使只有装饰器、没有 -> 注解,也不会让返回类型静默退化成 i32 HandlesImports:外部函数声明处同样报错,并删除下游已失效的 CReturnTypes 参数拼接死代码 HandlesReturn / HandlesFor / BaseTranslator:CurrentCReturnTypes 等机械改名(读写端一致,无行为变化) includes/c.py:保留 CReturn 名字作墓碑(删掉会让 @c.CReturn 变成未知属性、可能被静默忽略),docstring 写明已移除并指路 -> tuple[...];README 措辞同步
This commit is contained in:
1 parent
e5a6616f8b
commit
35de6321f6
9 files changed
+96
-86
No files matched your search
@@ -64,7 +64,7 @@ def main() -> CInt | CExport:
|
||||
| [01-overview.md](wiki/01-overview.md) | 语言概述、两阶段编译流程、SHA1 命名空间、`t.CDefine`/`t.CExport`/`t.CInline` 深度解析 |
|
||||
| [02-type-system.md](wiki/02-type-system.md) | 类型系统(基本类型、指针、数组、结构体、联合体、枚举、typedef、`__attribute__`) |
|
||||
| [03-variables.md](wiki/03-variables.md) | 变量声明与赋值(含 `t.CDefine` 常量) |
|
||||
| [04-functions.md](wiki/04-functions.md) | 函数定义与调用(含 `t.CExport`、`t.CInline`、`t.CDefine` 函数、`@c.CReturn`) |
|
||||
| [04-functions.md](wiki/04-functions.md) | 函数定义与调用(含 `t.CExport`、`t.CInline`、`t.CDefine` 函数、`-> tuple[...]` 多返回值) |
|
||||
| [05-classes.md](wiki/05-classes.md) | 类与数据布局(结构体、联合体、枚举、typedef、位域) |
|
||||
| [06-oop.md](wiki/06-oop.md) | 面向对象与运算符重载(`@t.Object`、`@t.CVTable`、`@t.NoVTable`、继承、dunder 方法) |
|
||||
| [07-control-flow.md](wiki/07-control-flow.md) | 控制流(条件、循环、match) |
|
||||
|
||||
@@ -182,24 +182,28 @@ class DeclarationGenerator:
|
||||
is_export: bool = self._is_export_func(node)
|
||||
if self.module_sha1 and not is_export:
|
||||
func_name = f"{self.module_sha1}.{func_name}"
|
||||
CReturnTypes: list[ast.AST] = []
|
||||
MultiRetTypes: list[ast.AST] = []
|
||||
if node.decorator_list:
|
||||
for decorator in node.decorator_list:
|
||||
# fail-fast:`@c.CReturn` 装饰器已移除,任何地方出现都必须报错,
|
||||
# 不得静默忽略或改写;多返回值请改用 `-> tuple[ty1, ty2, ...]`。
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
if decorator.func.attr == 'CReturn':
|
||||
for arg in decorator.args:
|
||||
CReturnTypes.append(arg)
|
||||
raise SyntaxError(
|
||||
f"函数 '{node.name}':`@c.CReturn` 已移除:请改用返回注解 "
|
||||
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
||||
)
|
||||
if node.returns:
|
||||
if isinstance(node.returns, ast.Subscript) and isinstance(node.returns.value, ast.Name) and node.returns.value.id == 'tuple':
|
||||
slice_node: ast.AST = node.returns.slice
|
||||
if isinstance(slice_node, ast.Tuple):
|
||||
for elt in slice_node.elts:
|
||||
CReturnTypes.append(elt)
|
||||
MultiRetTypes.append(elt)
|
||||
else:
|
||||
CReturnTypes.append(slice_node)
|
||||
MultiRetTypes.append(slice_node)
|
||||
ret_type: str
|
||||
if CReturnTypes:
|
||||
elem_types: list[str] = [self._get_type_str(rt, embedded=True) for rt in CReturnTypes]
|
||||
if MultiRetTypes:
|
||||
elem_types: list[str] = [self._get_type_str(rt, embedded=True) for rt in MultiRetTypes]
|
||||
ret_type = '{ ' + ', '.join(elem_types) + ' }'
|
||||
else:
|
||||
ret_type = self._get_type_str(node.returns)
|
||||
|
||||
@@ -536,31 +536,35 @@ class AssignHandle(BaseHandle):
|
||||
elif isinstance(Node.value.func, ast.Attribute):
|
||||
FuncName = Node.value.func.attr
|
||||
ModulePath = self.Trans.ExprCallHandle._get_ModulePath(Node.value.func.value)
|
||||
CReturnTypes: list[ast.expr] = []
|
||||
MultiRetTypes: list[ast.expr] = []
|
||||
FuncDef: ast.FunctionDef | None = self.Trans.FunctionDefCache.get(FuncName) if FuncName else None
|
||||
if FuncDef:
|
||||
if FuncDef.returns and isinstance(FuncDef.returns, ast.Subscript):
|
||||
if isinstance(FuncDef.returns.value, ast.Name) and FuncDef.returns.value.id == 'tuple':
|
||||
slice_node: ast.expr = FuncDef.returns.slice
|
||||
if isinstance(slice_node, ast.Tuple):
|
||||
CReturnTypes = slice_node.elts
|
||||
MultiRetTypes = slice_node.elts
|
||||
else:
|
||||
CReturnTypes = [slice_node]
|
||||
MultiRetTypes = [slice_node]
|
||||
if FuncDef.decorator_list:
|
||||
for decorator in FuncDef.decorator_list:
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
# fail-fast:`@c.CReturn` 已移除,扫到即报错。
|
||||
if decorator.func.attr == 'CReturn':
|
||||
for arg in decorator.args:
|
||||
CReturnTypes.append(arg)
|
||||
if not CReturnTypes and FuncName:
|
||||
raise SyntaxError(
|
||||
f"函数 '{FuncName}':`@c.CReturn` 已移除:请改用返回注解 "
|
||||
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
||||
f"{Gen._get_node_info()}"
|
||||
)
|
||||
if not MultiRetTypes and FuncName:
|
||||
func: ir.Function | None = Gen.functions.get(FuncName)
|
||||
if func:
|
||||
func_ft: ir.FunctionType | None = getattr(func, 'ftype', None)
|
||||
if func_ft:
|
||||
ret_type: ir.Type = func_ft.return_type
|
||||
if isinstance(ret_type, ir.LiteralStructType):
|
||||
CReturnTypes = [None] * len(ret_type.elements)
|
||||
if not CReturnTypes:
|
||||
MultiRetTypes = [None] * len(ret_type.elements)
|
||||
if not MultiRetTypes:
|
||||
sym_key: str = FuncName
|
||||
if not self.Trans.SymbolTable.has(sym_key):
|
||||
if ModulePath:
|
||||
@@ -575,7 +579,7 @@ class AssignHandle(BaseHandle):
|
||||
else:
|
||||
ret_type = Gen._type_str_to_llvm(str(ret_type_info) if ret_type_info else 'i32', False)
|
||||
if isinstance(ret_type, ir.LiteralStructType):
|
||||
CReturnTypes = [None] * len(ret_type.elements)
|
||||
MultiRetTypes = [None] * len(ret_type.elements)
|
||||
if FuncName not in Gen.functions:
|
||||
if isinstance(ret_type, ir.VoidType):
|
||||
ret_type = ir.IntType(32)
|
||||
@@ -593,18 +597,18 @@ class AssignHandle(BaseHandle):
|
||||
func_decl: ir.Function = ir.Function(Gen.module, func_type, name=MangledName)
|
||||
Gen.functions[MangledName] = func_decl
|
||||
Gen.functions[FuncName] = func_decl
|
||||
if not CReturnTypes and FuncName:
|
||||
if not MultiRetTypes and FuncName:
|
||||
func: ir.Function | None = Gen.functions.get(FuncName)
|
||||
if func:
|
||||
func_ft: ir.FunctionType | None = getattr(func, 'ftype', None)
|
||||
if func_ft:
|
||||
ret_type: ir.Type = func_ft.return_type
|
||||
if isinstance(ret_type, ir.LiteralStructType):
|
||||
CReturnTypes = [None] * len(ret_type.elements)
|
||||
if not CReturnTypes:
|
||||
MultiRetTypes = [None] * len(ret_type.elements)
|
||||
if not MultiRetTypes:
|
||||
# 跨模块多返回值兜底:短名未注册时(函数以 ModulePath.名 /
|
||||
# sha1.名 全名注册),从其 LiteralStructType 返回类型恢复 CReturnTypes。
|
||||
# 否则 CReturnTypes 为空会走下方静默 return,目标变量未初始化,
|
||||
# sha1.名 全名注册),从其 LiteralStructType 返回类型恢复 MultiRetTypes。
|
||||
# 否则 MultiRetTypes 为空会走下方静默 return,目标变量未初始化,
|
||||
# 运行期 free(垃圾指针) 触发堆损坏(HashLibTest 0xC0000374)。
|
||||
func = None
|
||||
if ModulePath:
|
||||
@@ -619,10 +623,10 @@ class AssignHandle(BaseHandle):
|
||||
if func_ft:
|
||||
ret_type: ir.Type = func_ft.return_type
|
||||
if isinstance(ret_type, ir.LiteralStructType):
|
||||
CReturnTypes = [None] * len(ret_type.elements)
|
||||
if CReturnTypes and len(Target.elts) == len(CReturnTypes):
|
||||
MultiRetTypes = [None] * len(ret_type.elements)
|
||||
if MultiRetTypes and len(Target.elts) == len(MultiRetTypes):
|
||||
# 注:此处原有两行 `if func is None: func = ...`,但 func 只在上面
|
||||
# 「not CReturnTypes」分支里绑定;当 CReturnTypes 来自返回注解
|
||||
# 「not MultiRetTypes」分支里绑定;当 MultiRetTypes 来自返回注解
|
||||
# (`-> tuple[T1, T2]`)时该分支未执行 ⇒ UnboundLocalError 崩溃。
|
||||
# 且紧接着的 `func = Gen.functions.get(FuncName)` 本就覆盖它,
|
||||
# 故直接删除(`a, b = f()` 因此从未真正跑通)。
|
||||
@@ -670,8 +674,8 @@ class AssignHandle(BaseHandle):
|
||||
VarName: str = elt.id
|
||||
field_val: ir.Value = Gen.builder.extract_value(call_result, j, name=f"extract_{FuncName}_{j}")
|
||||
VarType: ir.Type
|
||||
if CReturnTypes[j] is not None:
|
||||
ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(CReturnTypes[j], self.Trans.SymbolTable)
|
||||
if MultiRetTypes[j] is not None:
|
||||
ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(MultiRetTypes[j], self.Trans.SymbolTable)
|
||||
if ReturnTypeInfo is None:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = t.CInt()
|
||||
@@ -684,7 +688,7 @@ class AssignHandle(BaseHandle):
|
||||
VarType = ir.IntType(32)
|
||||
var: ir.AllocaInstr = Gen._alloca(VarType, name=VarName)
|
||||
Gen.variables[VarName] = var
|
||||
if CReturnTypes[j] is not None:
|
||||
if MultiRetTypes[j] is not None:
|
||||
Gen._record_var_signedness(VarName, str(ReturnTypeInfo) if ReturnTypeInfo else '')
|
||||
elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements):
|
||||
elem_type: ir.Type = ret_type.elements[j]
|
||||
@@ -697,7 +701,7 @@ class AssignHandle(BaseHandle):
|
||||
Gen._record_var_signedness(VarName, 'unsigned long long')
|
||||
Gen._store(field_val, var)
|
||||
elif isinstance(Node.value, ast.Call):
|
||||
# fail-fast:多返回值赋值但 CReturnTypes 解析失败(跨模块签名丢失),
|
||||
# fail-fast:多返回值赋值但 MultiRetTypes 解析失败(跨模块签名丢失),
|
||||
# 绝不能静默跳过——目标变量不会被初始化,运行期 free(垃圾指针)
|
||||
# 触发堆损坏(HashLibTest 0xC0000374)。
|
||||
target_names: list[str] = [
|
||||
@@ -705,7 +709,7 @@ class AssignHandle(BaseHandle):
|
||||
]
|
||||
raise Exception(
|
||||
f"多返回值赋值解析失败: '{FuncName}' 的返回类型无法解析为"
|
||||
f"元组/CReturn(ModulePath={ModulePath}),目标 {target_names} 未被初始化"
|
||||
f"返回注解 `-> tuple[...]`(ModulePath={ModulePath}),目标 {target_names} 未被初始化"
|
||||
f"{Gen._get_node_info()}"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -411,7 +411,7 @@ class ForHandle(BaseHandle):
|
||||
saved_var_signedness: dict[str, str] = Gen.var_signedness.copy()
|
||||
saved_var_type_info: dict[str, dict[str, str]] = Gen.var_type_info.copy()
|
||||
saved_var_type_assignments: dict[str, list[dict[str, str]]] = Gen.var_type_assignments.copy()
|
||||
saved_CurrentCReturnTypes: object | None = getattr(self.Trans, 'CurrentCReturnTypes', None)
|
||||
saved_CurrentMultiRetTypes: object | None = getattr(self.Trans, 'CurrentMultiRetTypes', None)
|
||||
saved_CurrentCpythonObjectClass: str | None = getattr(self.Trans, '_CurrentCpythonObjectClass', None)
|
||||
saved_VarScopes: int = len(self.Trans.VarScopes)
|
||||
self.Trans.FunctionHandler._EmitFunctionLlvm(Node, Gen, extra_params=extra_params if extra_params else None)
|
||||
@@ -423,7 +423,7 @@ class ForHandle(BaseHandle):
|
||||
Gen.var_signedness = saved_var_signedness
|
||||
Gen.var_type_info = saved_var_type_info
|
||||
Gen.var_type_assignments = saved_var_type_assignments
|
||||
self.Trans.CurrentCReturnTypes = saved_CurrentCReturnTypes
|
||||
self.Trans.CurrentMultiRetTypes = saved_CurrentMultiRetTypes
|
||||
self.Trans._CurrentCpythonObjectClass = saved_CurrentCpythonObjectClass
|
||||
while len(self.Trans.VarScopes) > saved_VarScopes:
|
||||
self.Trans.VarScopes.pop()
|
||||
|
||||
@@ -20,6 +20,20 @@ from lib.includes.t import CTypeRegistry
|
||||
# t 模块存储类标记装饰器名称集合
|
||||
_T_STORAGE_DECORATORS = frozenset({'CExport', 'CExtern', 'CStatic', 'State', 'CInline', 'TLS'})
|
||||
|
||||
# `@c.CReturn` 装饰器已移除;任何地方遇到都必须 fail-fast,不得静默忽略或改写。
|
||||
_CRETURN_REMOVED_HINT: str = (
|
||||
"`@c.CReturn` 已移除:请改用返回注解 `-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
||||
)
|
||||
|
||||
|
||||
def _RejectCReturnDecorator(node: ast.AST, decorators: list[ast.AST]) -> None:
|
||||
"""扫到 `@c.CReturn` 装饰器即 fail-fast 报错(该装饰器已移除)。"""
|
||||
for decorator in decorators:
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
if decorator.func.attr == 'CReturn':
|
||||
func_name: str = getattr(node, 'name', '<unknown>')
|
||||
raise SyntaxError(f"函数 '{func_name}':{_CRETURN_REMOVED_HINT}")
|
||||
|
||||
|
||||
def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
|
||||
"""判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。
|
||||
@@ -489,13 +503,9 @@ class FunctionHandle(BaseHandle):
|
||||
|
||||
def _GetFunctionSignatureLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None, extra_params: list[tuple[str, Any]] | None = None) -> tuple[str, ir.FunctionType, Any, list[Any], list[ast.AST], bool, str | None, bool]:
|
||||
FuncName, RawFuncName, func_meta = self._compute_func_name_meta(Node, ClassName)
|
||||
CReturnTypes: list[ast.AST] = []
|
||||
if Node.decorator_list:
|
||||
for decorator in Node.decorator_list:
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
if decorator.func.attr == 'CReturn':
|
||||
for arg in decorator.args:
|
||||
CReturnTypes.append(arg)
|
||||
_RejectCReturnDecorator(Node, Node.decorator_list)
|
||||
MultiRetTypes: list[ast.AST] = []
|
||||
if Node.returns:
|
||||
llvm_attrs: list[str] = self._ExtractLLVMAttrs(Node.returns)
|
||||
if llvm_attrs:
|
||||
@@ -506,13 +516,13 @@ class FunctionHandle(BaseHandle):
|
||||
slice_node: ast.AST = Node.returns.slice
|
||||
if isinstance(slice_node, ast.Tuple):
|
||||
for elt in slice_node.elts:
|
||||
CReturnTypes.append(elt)
|
||||
MultiRetTypes.append(elt)
|
||||
else:
|
||||
CReturnTypes.append(slice_node)
|
||||
MultiRetTypes.append(slice_node)
|
||||
IsPtr: bool = False
|
||||
ReturnTypeInfo: Any = None
|
||||
if Node.returns:
|
||||
if CReturnTypes:
|
||||
if MultiRetTypes:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = t.CVoid()
|
||||
else:
|
||||
@@ -672,9 +682,9 @@ class FunctionHandle(BaseHandle):
|
||||
ParamNames: list[str] = []
|
||||
ParamTypeStrs: list[Any] = []
|
||||
auto_addr_modes: list[str | None] = []
|
||||
CReturnLlvmTypes: list[ir.Type] = []
|
||||
if CReturnTypes:
|
||||
for i, ReturnTypeNode in enumerate(CReturnTypes):
|
||||
MultiRetLlvmTypes: list[ir.Type] = []
|
||||
if MultiRetTypes:
|
||||
for i, ReturnTypeNode in enumerate(MultiRetTypes):
|
||||
ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable)
|
||||
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。
|
||||
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
|
||||
@@ -686,8 +696,8 @@ class FunctionHandle(BaseHandle):
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = t.CInt()
|
||||
RetType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo)
|
||||
CReturnLlvmTypes.append(RetType)
|
||||
ReturnType = ir.LiteralStructType(CReturnLlvmTypes)
|
||||
MultiRetLlvmTypes.append(RetType)
|
||||
ReturnType = ir.LiteralStructType(MultiRetLlvmTypes)
|
||||
for Arg in Node.args.args:
|
||||
ParamIsUnsigned: bool = False
|
||||
if Arg.annotation:
|
||||
@@ -782,7 +792,7 @@ class FunctionHandle(BaseHandle):
|
||||
while len(auto_addr_modes) < total_params:
|
||||
auto_addr_modes.append(None)
|
||||
Gen._auto_addr_params[FuncName] = auto_addr_modes
|
||||
return FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic
|
||||
return FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, MultiRetTypes, IsMethod, ResolvedClassName, IsVariadic
|
||||
|
||||
def _is_generic_function(self, Node: ast.FunctionDef) -> bool:
|
||||
if hasattr(Node, 'type_params') and Node.type_params:
|
||||
@@ -1201,11 +1211,11 @@ class FunctionHandle(BaseHandle):
|
||||
FuncType: ir.FunctionType
|
||||
ReturnTypeInfo: Any
|
||||
ParamTypeStrs: list[Any]
|
||||
CReturnTypes: list[ast.AST]
|
||||
MultiRetTypes: list[ast.AST]
|
||||
IsMethod: bool
|
||||
ResolvedClassName: str | None
|
||||
IsVariadic: bool
|
||||
FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic = result
|
||||
FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, MultiRetTypes, IsMethod, ResolvedClassName, IsVariadic = result
|
||||
IsUserMarkedExport: bool = False
|
||||
if Node.returns:
|
||||
try:
|
||||
@@ -1315,7 +1325,7 @@ class FunctionHandle(BaseHandle):
|
||||
# 保存父级 _CurrentCpythonObjectClass,防止嵌套函数发射污染父方法类上下文
|
||||
# (例如 HandleImport body 内触发 list[ast.ASTptr] 方法发射,结束后会清空 _CurrentCpythonObjectClass)
|
||||
saved_cpython_class: str | None = self.Trans._CurrentCpythonObjectClass
|
||||
CReturnTypes = []
|
||||
MultiRetTypes = []
|
||||
IsPtr = False
|
||||
fn_attrs = {}
|
||||
# 自定义行为装饰器列表,用于生成 wrapper 函数
|
||||
@@ -1349,8 +1359,7 @@ class FunctionHandle(BaseHandle):
|
||||
continue
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
if decorator.func.attr == 'CReturn':
|
||||
for arg in decorator.args:
|
||||
CReturnTypes.append(arg)
|
||||
_RejectCReturnDecorator(Node, [decorator])
|
||||
elif decorator.func.attr == 'Attribute' and isinstance(decorator.func.value, ast.Name) and decorator.func.value.id == 'c':
|
||||
for arg in decorator.args:
|
||||
if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute):
|
||||
@@ -1396,9 +1405,9 @@ class FunctionHandle(BaseHandle):
|
||||
slice_node = Node.returns.slice
|
||||
if isinstance(slice_node, ast.Tuple):
|
||||
for elt in slice_node.elts:
|
||||
CReturnTypes.append(elt)
|
||||
MultiRetTypes.append(elt)
|
||||
else:
|
||||
CReturnTypes.append(slice_node)
|
||||
MultiRetTypes.append(slice_node)
|
||||
|
||||
# 先强制检查 str 类型注解
|
||||
is_str_return = False
|
||||
@@ -1423,7 +1432,7 @@ class FunctionHandle(BaseHandle):
|
||||
ReturnTypeInfo.BaseType = t.CChar()
|
||||
ReturnTypeInfo.PtrCount = 1
|
||||
elif Node.returns:
|
||||
if CReturnTypes:
|
||||
if MultiRetTypes:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = t.CVoid()
|
||||
else:
|
||||
@@ -1634,9 +1643,9 @@ class FunctionHandle(BaseHandle):
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
if CReturnTypes:
|
||||
CReturnLlvmTypes = []
|
||||
for i, ReturnTypeNode in enumerate(CReturnTypes):
|
||||
if MultiRetTypes:
|
||||
MultiRetLlvmTypes = []
|
||||
for i, ReturnTypeNode in enumerate(MultiRetTypes):
|
||||
ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable)
|
||||
# 仅指针层数 <=1 才算裸 str/bytes(i8*)。
|
||||
# `str | t.CPtr` 合并后 IsStr=True 但 PtrCount=2(i8**,如 argv 数组),不能压平。
|
||||
@@ -1648,11 +1657,11 @@ class FunctionHandle(BaseHandle):
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = t.CInt()
|
||||
RetType = Gen._ctype_to_llvm(ReturnTypeInfo)
|
||||
CReturnLlvmTypes.append(RetType)
|
||||
ReturnType = ir.LiteralStructType(CReturnLlvmTypes)
|
||||
self.Trans.CurrentCReturnTypes = CReturnTypes
|
||||
MultiRetLlvmTypes.append(RetType)
|
||||
ReturnType = ir.LiteralStructType(MultiRetLlvmTypes)
|
||||
self.Trans.CurrentMultiRetTypes = MultiRetTypes
|
||||
else:
|
||||
self.Trans.CurrentCReturnTypes = None
|
||||
self.Trans.CurrentMultiRetTypes = None
|
||||
self._apply_struct_self_cls_types(ParamTypes, ParamNames, IsMethod, IsClassMethod, ResolvedClassName, Gen)
|
||||
IsVariadic = Node.args.vararg is not None
|
||||
if extra_params:
|
||||
@@ -2160,7 +2169,7 @@ class FunctionHandle(BaseHandle):
|
||||
Gen.global_struct_class = saved_global_struct_class
|
||||
Gen._variadic_info = None
|
||||
self.Trans._CurrentCpythonObjectClass = saved_cpython_class
|
||||
self.Trans.CurrentCReturnTypes = None
|
||||
self.Trans.CurrentMultiRetTypes = None
|
||||
if self.Trans.VarScopes:
|
||||
self.Trans.VarScopes.pop()
|
||||
self.Trans.FunctionReturnTypes[FuncName] = ReturnTypeInfo
|
||||
|
||||
@@ -1421,13 +1421,15 @@ class ImportHandle(BaseHandle):
|
||||
Gen._export_extern_funcs[FuncName] = _src_sha1
|
||||
if FuncName in Gen.functions:
|
||||
return
|
||||
CReturnTypes = []
|
||||
if Node.decorator_list:
|
||||
for decorator in Node.decorator_list:
|
||||
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute):
|
||||
# fail-fast:`@c.CReturn` 已移除,扫到即报错。
|
||||
if decorator.func.attr == 'CReturn':
|
||||
for arg in decorator.args:
|
||||
CReturnTypes.append(arg)
|
||||
raise SyntaxError(
|
||||
f"函数 '{FuncName}':`@c.CReturn` 已移除:请改用返回注解 "
|
||||
f"`-> tuple[ty1, ty2, ...]`(多返回值打包为 struct)"
|
||||
)
|
||||
IsPtr = False
|
||||
ReturnTypeInfo = None
|
||||
if Node.returns:
|
||||
@@ -1567,9 +1569,6 @@ class ImportHandle(BaseHandle):
|
||||
else:
|
||||
ParamType = ir.IntType(32)
|
||||
ParamTypes.append(ParamType)
|
||||
if CReturnTypes:
|
||||
for _ in CReturnTypes:
|
||||
ParamTypes.append(ir.PointerType(ir.IntType(8)))
|
||||
IsVariadic = Node.args.vararg is not None
|
||||
FuncType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic)
|
||||
_is_export = False
|
||||
|
||||
@@ -81,19 +81,19 @@ class ReturnHandle(BaseHandle):
|
||||
Gen.emit_return(closure_ret)
|
||||
return
|
||||
active_finally: tuple[ir.Block, ir.AllocaInstr, ir.AllocaInstr | None] | None = self._find_active_finally(Gen)
|
||||
if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes and Node.value:
|
||||
if getattr(self.Trans, 'CurrentMultiRetTypes', None) and self.Trans.CurrentMultiRetTypes and Node.value:
|
||||
return_values: list[ast.expr] = []
|
||||
if isinstance(Node.value, ast.Tuple):
|
||||
return_values = Node.value.elts
|
||||
else:
|
||||
return_values = [Node.value]
|
||||
if len(return_values) == len(self.Trans.CurrentCReturnTypes):
|
||||
if len(return_values) == len(self.Trans.CurrentMultiRetTypes):
|
||||
llvm_vals: list[ir.Value] = []
|
||||
expected_types: list[ir.Type] = []
|
||||
for i, val in enumerate(return_values):
|
||||
ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(self.Trans.CurrentCReturnTypes[i], self.Trans.SymbolTable)
|
||||
ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(self.Trans.CurrentMultiRetTypes[i], self.Trans.SymbolTable)
|
||||
IsRetPtr: bool = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False
|
||||
if (isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsStr) or (isinstance(self.Trans.CurrentCReturnTypes[i], ast.Name) and self.Trans.CurrentCReturnTypes[i].id == 'str'):
|
||||
if (isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsStr) or (isinstance(self.Trans.CurrentMultiRetTypes[i], ast.Name) and self.Trans.CurrentMultiRetTypes[i].id == 'str'):
|
||||
IsRetPtr = True
|
||||
ExpectedType: ir.Type = ReturnTypeInfo.ToLLVM(Gen) if ReturnTypeInfo and ReturnTypeInfo.BaseType else Gen._CType2LLVM('int', IsRetPtr)
|
||||
expected_types.append(ExpectedType)
|
||||
@@ -161,7 +161,7 @@ class ReturnHandle(BaseHandle):
|
||||
else:
|
||||
Gen.emit_return(zero_val)
|
||||
return
|
||||
if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes:
|
||||
if getattr(self.Trans, 'CurrentMultiRetTypes', None) and self.Trans.CurrentMultiRetTypes:
|
||||
struct_type: ir.Type = Gen.func.ftype.return_type
|
||||
if isinstance(struct_type, ir.LiteralStructType):
|
||||
result: ir.Value = ir.Constant(struct_type, ir.Undefined)
|
||||
|
||||
@@ -44,7 +44,7 @@ class BaseTranslatorMixin:
|
||||
def __init__(self) -> None:
|
||||
self.VarScopes: list[Dict[str, SymbolNode]] = [{}] # 跟踪变量作用域,第一个是全局作用域
|
||||
self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型
|
||||
self.CurrentCReturnTypes: list[CTypeInfo] | None = None # 当前函数的 CReturn 类型列表
|
||||
self.CurrentMultiRetTypes: list[CTypeInfo] | None = None # 当前函数的多返回值类型列表(`-> tuple[...]`)
|
||||
self._CurrentCpythonObjectClass: str | None = None # 当前正在处理的 CPython 对象类名
|
||||
self.FunctionDefCache: dict = {} # 函数定义缓存
|
||||
self.OriginalLines: list[str] = [] # 原始代码行
|
||||
|
||||
+5
-11
@@ -417,17 +417,11 @@ class Set:
|
||||
|
||||
|
||||
class CReturn:
|
||||
"""多返回值装饰器
|
||||
|
||||
用于实现函数多返回值,通过匿名结构体返回实现。
|
||||
例如:@c.CReturn(t.CInt, t.CInt) 表示函数返回两个 int 值。
|
||||
等价于 -> tuple[t.CInt, t.CInt] 返回类型注解。
|
||||
|
||||
规则:
|
||||
1. CReturn 中有几个类型就说明要返回几个值
|
||||
2. 函数返回类型为匿名结构体 { type1, type2, ... }
|
||||
3. return 语句使用 insert_value 构建结构体
|
||||
4. 调用处使用 extract_value 提取各字段
|
||||
"""【已移除】多返回值装饰器(墓碑)。
|
||||
|
||||
该类已移除:源码中写 `@c.CReturn(...)` 会被编译器**报错**(fail-fast),
|
||||
不会静默忽略或改写。多返回值请改用返回注解 `-> tuple[ty1, ty2, ...]`
|
||||
(返回多个值的函数打包为 struct 返回,调用处用元组解包接收)。
|
||||
"""
|
||||
def __init__(self, *ReturnTypes: Any) -> None:
|
||||
self.ReturnTypes: tuple[Any, ...] = ReturnTypes
|
||||
|
||||
Reference in new issue
Block a user