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

54 lines
2.7 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 llvmlite.ir as ir
class WhileHandle(BaseHandle):
def _HandleWhileLlvm(self, Node: ast.While) -> None:
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
if Gen._direct_values:
for var_name in list(Gen._direct_values.keys()):
OldVal: ir.Value = Gen._direct_values.pop(var_name)
if var_name not in Gen.variables or Gen.variables.get(var_name) is None:
saved_block: ir.Block = Gen.builder.block
entry_block: ir.Block = Gen.func.entry_basic_block
Gen.builder.position_at_start(entry_block)
var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=var_name)
Gen._store(OldVal, var)
Gen.builder.position_at_end(saved_block)
Gen.variables[var_name] = var
CondBB: ir.Block = Gen.func.append_basic_block(name="while.cond")
BodyBB: ir.Block = Gen.func.append_basic_block(name="while.body")
ElseBB: ir.Block | None = Gen.func.append_basic_block(name="while.else") if Node.orelse else None
AfterBB: ir.Block = Gen.func.append_basic_block(name="while.end")
Gen.loop_break_targets.append(AfterBB)
Gen.loop_continue_targets.append(CondBB)
Gen.builder.branch(CondBB)
Gen.builder.position_at_start(CondBB)
Cond: ir.Value | None = self.HandleExprLlvm(Node.test)
if Cond:
if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1:
if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)):
Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="whilecond")
else:
Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="whilecond")
if not Gen.builder.block.is_terminated:
Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB)
else:
if not Gen.builder.block.is_terminated:
Gen.builder.branch(ElseBB if ElseBB else AfterBB)
Gen.builder.position_at_start(BodyBB)
self.HandleBodyLlvm(Node.body)
if not Gen.builder.block.is_terminated:
Gen.builder.branch(CondBB)
Gen.loop_break_targets.pop()
Gen.loop_continue_targets.pop()
if ElseBB:
Gen.builder.position_at_start(ElseBB)
self.HandleBodyLlvm(Node.orelse)
if not Gen.builder.block.is_terminated:
Gen.builder.branch(AfterBB)
Gen.builder.position_at_start(AfterBB)