删除 lib/includes/t.py、c.py,类型模型迁入 lib/core/TypeSystem.py;移除 IsTModule/_T_MODULE_NAMES 等名称判据,语法糖与内部标记统一为裸名;builtins 的 sizet/intN/uintN/fast/least/uchar/short/long 等改为编译器内建短名。
112 lines
6.5 KiB
Python
112 lines
6.5 KiB
Python
from __future__ import annotations
|
||
from typing import TYPE_CHECKING
|
||
if TYPE_CHECKING:
|
||
from lib.core.translator import Translator
|
||
from lib.core.Handles.HandlesBase import BaseHandle
|
||
import vast as ast
|
||
import llvmlite.ir as ir
|
||
|
||
|
||
class BodyHandle(BaseHandle):
|
||
def __init__(self, translator: "Translator") -> None:
|
||
super().__init__(translator)
|
||
|
||
def HandleBodyLlvm(self, Body: list[ast.stmt]) -> None:
|
||
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
|
||
for Node in Body:
|
||
if Gen.builder and Gen.builder.block.is_terminated:
|
||
break
|
||
Gen._set_node_info(Node)
|
||
try:
|
||
if isinstance(Node, ast.Expr):
|
||
# `fallthrough`(vast 关键字已脱糖为 NoBreak())是 switch 的
|
||
# 标记语句,本身不产出 IR,语义由 HandlesMatch 消费(case 体因此
|
||
# 不自动跳出 switch);合法位置**只有 switch 的 case 体内**,
|
||
# match(完全禁止 fallthrough)或 switch 之外一律 fail-fast。
|
||
if self._IsNoBreakMarkerStmt(Node):
|
||
if not Gen.in_switch_case:
|
||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||
raise FailFastError(
|
||
"fallthrough 只能用在 switch 的 case 体内"
|
||
"(match 完全禁止 fallthrough)")
|
||
else:
|
||
self.HandleExprLlvm(Node.value)
|
||
elif isinstance(Node, ast.Return):
|
||
self.Trans.ReturnHandler._HandleReturnLlvm(Node)
|
||
elif isinstance(Node, ast.Assign):
|
||
self.Trans.AssignHandler._HandleAssignLlvm(Node)
|
||
elif isinstance(Node, ast.AugAssign):
|
||
self.Trans.AugAssignHandler._HandleAugAssignLlvm(Node)
|
||
elif isinstance(Node, ast.AnnAssign):
|
||
self.Trans.AnnAssignHandler._HandleAnnAssignLlvm(Node)
|
||
elif isinstance(Node, ast.If):
|
||
self.Trans.IfHandler._HandleIfLlvm(Node)
|
||
elif isinstance(Node, ast.For):
|
||
self.Trans.ForHandler._HandleForLlvm(Node)
|
||
elif isinstance(Node, ast.While):
|
||
self.Trans.WhileHandler._HandleWhileLlvm(Node)
|
||
elif isinstance(Node, ast.Break):
|
||
if not Gen.loop_break_targets:
|
||
# fail-fast:循环 / switch / match-case 之外的 break 无处可跳,
|
||
# 静默忽略只会让"提前退出"变成无声无效果(不兜底)
|
||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||
raise FailFastError(
|
||
"break 只能用在循环或 switch/match 的 case 体内(当前没有可跳出的目标)")
|
||
Gen.builder.branch(Gen.loop_break_targets[-1])
|
||
elif isinstance(Node, ast.Continue):
|
||
if not Gen.loop_continue_targets:
|
||
# fail-fast:循环之外的 continue 无处可跳(同上)
|
||
from lib.core.LLVMCG.FuncGen import FailFastError
|
||
raise FailFastError(
|
||
"continue 只能用在循环体内(当前没有可继续的循环)")
|
||
Gen.builder.branch(Gen.loop_continue_targets[-1])
|
||
elif isinstance(Node, ast.With):
|
||
self.Trans.WithHandler._HandleWithLlvm(Node)
|
||
elif isinstance(Node, ast.ClassDef):
|
||
pass
|
||
elif getattr(ast, 'Match', None) and isinstance(Node, ast.Match):
|
||
self.Trans.MatchHandler._HandleMatchLlvm(Node)
|
||
elif isinstance(Node, ast.Try):
|
||
self.Trans.TryHandler._HandleTryLlvm(Node)
|
||
elif isinstance(Node, ast.Raise):
|
||
self.Trans.RaiseHandler._HandleRaiseLlvm(Node)
|
||
elif isinstance(Node, ast.Assert):
|
||
self.Trans.AssertHandler._HandleAssertLlvm(Node)
|
||
elif isinstance(Node, ast.Global):
|
||
self.Trans.ForHandler._HandleGlobalLlvm(Node)
|
||
elif isinstance(Node, ast.FunctionDef):
|
||
self.Trans.ForHandler._HandleNestedFunctionLlvm(Node)
|
||
elif isinstance(Node, ast.Nonlocal):
|
||
self.Trans.ForHandler._HandleNonlocalLlvm(Node)
|
||
elif isinstance(Node, ast.Delete):
|
||
self.Trans.DeleteHandler._HandleDeleteLlvm(Node)
|
||
except Exception as e:
|
||
lineno: int = getattr(Node, 'lineno', 0)
|
||
# 注入行偏移还原:AST 行号含 _inject_auto_imports 在文件头注入的 N 行,
|
||
# 先按精确偏移减回磁盘真实行号(N 由 Phase2Translator 计算并挂到 translator);
|
||
# 报文行号与源码行必须同用还原后的 lineno,二者一致(否则会显示下一行源码)。
|
||
_line_offset: int = int(getattr(self.Trans, '_line_offset', 0) or 0)
|
||
if _line_offset > 0 and lineno > _line_offset:
|
||
lineno -= _line_offset
|
||
source_line: str | None = Gen._get_source_line(lineno)
|
||
src_file: str = Gen._current_source_file or ''
|
||
src_path: str = src_file if src_file else 'unknown'
|
||
line_info: str = "源代码 (%s, line %d)" % (src_path, lineno)
|
||
if source_line:
|
||
line_info += ":\n %d | %s" % (lineno, source_line)
|
||
self.Trans._ErrorStack.append((type(e).__name__, str(e), line_info))
|
||
raise
|
||
if Gen.builder and not Gen.builder.block.is_terminated:
|
||
Gen._EmitTempFrees()
|
||
|
||
@staticmethod
|
||
def _IsNoBreakMarkerStmt(Node: ast.stmt) -> bool:
|
||
"""是否 `NoBreak()` 标记语句(`fallthrough` 软关键字的脱糖形态)"""
|
||
if not isinstance(Node, ast.Expr) or not isinstance(Node.value, ast.Call):
|
||
return False
|
||
Fn: ast.expr = Node.value.func
|
||
return isinstance(Fn, ast.Name) and Fn.id == 'NoBreak'
|
||
|
||
def HandleExprLlvm(self, Node: ast.expr, VarType: ir.Type | None = None,
|
||
ConstWidthHint: int | None = None) -> ir.Value | None:
|
||
return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType, ConstWidthHint) |