Files
TransPyC/TransPyV/App/lib/core/Handles/HandlesBody.py
2026-07-18 19:25:40 +08:00

231 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import viperlib
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.Handles.HandlesClassDef as HandlesClassDef
# ============================================================
# HandlesBody - 语句分派trans 单参模式,全方法调用)
#
# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。
# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。
# ============================================================
# ============================================================
# 语句翻译分派
# ============================================================
def translate_stmt(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译单条语句,返回新增的变量数"""
if node is None:
return 0
k: int = node.kind()
if k == ast.ASTKind.Expr:
return translate_expr_stmt(trans, node)
elif k == ast.ASTKind.Assign:
return trans.AssignH.Handle(node)
elif k == ast.ASTKind.AnnAssign:
return trans.AnnAssignH.Handle(node)
elif k == ast.ASTKind.FunctionDef:
# 嵌套函数定义:提升为顶层函数 + 创建闭包
return HandlesFunctions.translate_nested_function_def(trans, node)
elif k == ast.ASTKind.Return:
return trans.ReturnH.Handle(node)
elif k == ast.ASTKind.If:
return trans.IfH.Handle(node)
elif k == ast.ASTKind.While:
return trans.WhileH.Handle(node)
elif k == ast.ASTKind.AugAssign:
return trans.AugAssignH.Handle(node)
elif k == ast.ASTKind.For:
return trans.ForH.Handle(node)
elif k == ast.ASTKind.ClassDef:
return HandlesClassDef.translate_class_def(trans, node)
elif k == ast.ASTKind.Import:
return trans.ImportsH.HandleImport(node)
elif k == ast.ASTKind.ImportFrom:
trans.ImportsH.HandleImportFromModule(node)
return trans.ImportsH.HandleImportFromNames(node)
elif k == ast.ASTKind.Global:
return translate_global(trans, node)
elif k == ast.ASTKind.Nonlocal:
return translate_nonlocal(trans, node)
elif k == ast.ASTKind.Pass:
return 0
elif k == ast.ASTKind.Break:
return translate_break(trans)
elif k == ast.ASTKind.Continue:
return translate_continue(trans)
return 0
# ============================================================
# 翻译 Global 语句: global x, y
#
# 将 names 中的变量名加入 _global_names 集合
# ============================================================
def translate_global(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 global 语句:记录 global 变量名"""
gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node)
if gn is None:
return 0
names: list[ast.AST | t.CPtr] | t.CPtr = gn.names
if names is None:
return 0
n: t.CSizeT = names.__len__()
for i in range(n):
nm_node: ast.AST | t.CPtr = names.get(i)
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
if nm.id is not None:
HT.add_global_name(trans, nm.id)
return 0
# ============================================================
# 翻译 Nonlocal 语句: nonlocal x, y
#
# 将 names 中的变量名加入 _nonlocal_names 集合
# ============================================================
def translate_nonlocal(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 nonlocal 语句:记录 nonlocal 变量名"""
nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node)
if nl is None:
return 0
names: list[ast.AST | t.CPtr] | t.CPtr = nl.names
if names is None:
return 0
n: t.CSizeT = names.__len__()
for i in range(n):
nm_node: ast.AST | t.CPtr = names.get(i)
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
if nm.id is not None:
HT.add_nonlocal_name(trans, nm.id)
return 0
# ============================================================
# 翻译表达式语句 Expr(value=Call(...))
# ============================================================
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译表达式语句printf 调用等)"""
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
if ex is None:
return 0
call_node: ast.AST | t.CPtr = ex.value
if call_node is None:
return 0
ck: int = call_node.kind()
if ck != ast.ASTKind.Call:
return 0
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node)
func_node: ast.AST | t.CPtr = cl.func
if func_node is None:
return 0
func_name: str = HandlesExpr.get_func_name(func_node)
if func_name is None:
return 0
# printf / print 走特殊路径print 映射到 printf
if string.strcmp(func_name, "printf") == 0 or string.strcmp(func_name, "print") == 0:
trans.ExprCallH.HandlePrintfCall(cl)
else:
# 通用函数调用(返回值丢弃)
trans.ExprCallH.HandleCall(call_node)
return 0
# ============================================================
# 预扫描:为局部变量提前创建 alloca
# ============================================================
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""预扫描语句中的 AnnAssign提前创建 alloca
返回新增的变量数
"""
if node is None:
return 0
return trans.AnnAssignH.PreScan(node)
# ============================================================
# 翻译 break 语句
# ============================================================
def translate_break(trans: HT.Translator | t.CPtr) -> int:
"""翻译 break 语句:跳转到循环 end 块"""
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
func: llvmlite.Function | t.CPtr = trans._cur_func
pool: memhub.MemBuddy | t.CPtr = trans.Pool
if builder is None or func is None:
return 0
# 发射 br 到 break 目标
if trans._break_bb is not None:
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._break_bb)
# 创建死代码 BB用于后续语句break 后面的代码不可达)
cnt: int = trans._label_counter
trans._label_counter = cnt + 1
name_buf: t.CChar | t.CPtr = pool.alloc(32)
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
llvmlite.position_at_end(builder, dead_bb)
return 0
# ============================================================
# 翻译 continue 语句
# ============================================================
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
func: llvmlite.Function | t.CPtr = trans._cur_func
pool: memhub.MemBuddy | t.CPtr = trans.Pool
if builder is None or func is None:
return 0
# 发射 br 到 continue 目标
if trans._continue_bb is not None:
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._continue_bb)
# 创建死代码 BB用于后续语句
cnt: int = trans._label_counter
trans._label_counter = cnt + 1
name_buf: t.CChar | t.CPtr = pool.alloc(32)
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
llvmlite.position_at_end(builder, dead_bb)
return 0
# ============================================================
# 获取语句类型名(调试用)
# ============================================================
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
"""获取语句类型名"""
if node is None:
return None
return node.type_name()