- vast/Parser:语句位置识别裸 `fallthrough`(仅整条语句命中),脱糖为 c.NoBreak() 标记调用;作标识符的写法不受影响 - HandlesBody:`c.NoBreak()` 标记语句不产出 IR(语义由 HandlesMatch 消费) - HandlesMatch:新增 _HandleMatchCaseBody(case 内 break 目标 = match 的 AfterBB, 经 loop_break_targets 压栈/出栈,不影响外层循环)与 _FallThroughTarget; 9 处 fallthrough 由"只留无终结符块"改为显式 br 下一个 case body
99 lines
5.4 KiB
Python
99 lines
5.4 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 软关键字已脱糖为 c.NoBreak())是 match 的
|
||
# 标记语句,本身不产出 IR,语义由 HandlesMatch 消费;后续步骤
|
||
# (含 _EmitTempFrees)保持原样执行。
|
||
if self._IsNoBreakMarkerStmt(Node):
|
||
pass
|
||
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 Gen.loop_break_targets:
|
||
Gen.builder.branch(Gen.loop_break_targets[-1])
|
||
elif isinstance(Node, ast.Continue):
|
||
if Gen.loop_continue_targets:
|
||
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:
|
||
"""是否 `c.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.Attribute) and isinstance(Fn.value, ast.Name)
|
||
and Fn.value.id == 'c' and Fn.attr == '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) |