use super::*;
pub(crate) fn lower_branch_cond(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
cond: BranchCond,
) -> HirExpr {
let expr = lower_branch_subject(lowering, block, instr_ref, cond);
if cond.negated {
HirExpr::Unary(Box::new(HirUnaryExpr {
op: HirUnaryOpKind::Not,
expr,
}))
} else {
expr
}
}
pub(crate) fn lower_branch_subject(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
cond: BranchCond,
) -> HirExpr {
match cond.operands {
BranchOperands::Unary(operand) => match cond.predicate {
BranchPredicate::Truthy => lower_cond_operand(lowering, block, instr_ref, operand),
_ => unresolved_expr("unsupported unary branch predicate"),
},
BranchOperands::Binary(lhs, rhs) => HirExpr::Binary(Box::new(HirBinaryExpr {
op: match cond.predicate {
BranchPredicate::Eq => HirBinaryOpKind::Eq,
BranchPredicate::Lt => HirBinaryOpKind::Lt,
BranchPredicate::Le => HirBinaryOpKind::Le,
BranchPredicate::Truthy => {
return unresolved_expr("unsupported truthy binary branch");
}
},
lhs: lower_cond_operand(lowering, block, instr_ref, lhs),
rhs: lower_cond_operand(lowering, block, instr_ref, rhs),
})),
}
}
pub(crate) fn lower_branch_subject_inline(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
cond: BranchCond,
) -> HirExpr {
match cond.operands {
BranchOperands::Unary(operand) => match cond.predicate {
BranchPredicate::Truthy => {
lower_cond_operand_inline(lowering, block, instr_ref, operand)
}
_ => unresolved_expr("unsupported unary branch predicate"),
},
BranchOperands::Binary(lhs, rhs) => HirExpr::Binary(Box::new(HirBinaryExpr {
op: match cond.predicate {
BranchPredicate::Eq => HirBinaryOpKind::Eq,
BranchPredicate::Lt => HirBinaryOpKind::Lt,
BranchPredicate::Le => HirBinaryOpKind::Le,
BranchPredicate::Truthy => {
return unresolved_expr("unsupported truthy binary branch");
}
},
lhs: lower_cond_operand_inline(lowering, block, instr_ref, lhs),
rhs: lower_cond_operand_inline(lowering, block, instr_ref, rhs),
})),
}
}
pub(crate) fn lower_branch_subject_single_eval(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
cond: BranchCond,
) -> HirExpr {
match cond.operands {
BranchOperands::Unary(operand) => match cond.predicate {
BranchPredicate::Truthy => {
lower_cond_operand_single_eval(lowering, block, instr_ref, operand)
}
_ => unresolved_expr("unsupported unary branch predicate"),
},
BranchOperands::Binary(lhs, rhs) => HirExpr::Binary(Box::new(HirBinaryExpr {
op: match cond.predicate {
BranchPredicate::Eq => HirBinaryOpKind::Eq,
BranchPredicate::Lt => HirBinaryOpKind::Lt,
BranchPredicate::Le => HirBinaryOpKind::Le,
BranchPredicate::Truthy => {
return unresolved_expr("unsupported truthy binary branch");
}
},
lhs: lower_cond_operand_single_eval(lowering, block, instr_ref, lhs),
rhs: lower_cond_operand_single_eval(lowering, block, instr_ref, rhs),
})),
}
}
pub(crate) fn lower_unary_op(op: UnaryOpKind) -> HirUnaryOpKind {
match op {
UnaryOpKind::Not => HirUnaryOpKind::Not,
UnaryOpKind::Neg => HirUnaryOpKind::Neg,
UnaryOpKind::BitNot => HirUnaryOpKind::BitNot,
UnaryOpKind::Length => HirUnaryOpKind::Length,
}
}
pub(crate) fn lower_binary_op(op: BinaryOpKind) -> HirBinaryOpKind {
match op {
BinaryOpKind::Add => HirBinaryOpKind::Add,
BinaryOpKind::Sub => HirBinaryOpKind::Sub,
BinaryOpKind::Mul => HirBinaryOpKind::Mul,
BinaryOpKind::Div => HirBinaryOpKind::Div,
BinaryOpKind::FloorDiv => HirBinaryOpKind::FloorDiv,
BinaryOpKind::Mod => HirBinaryOpKind::Mod,
BinaryOpKind::Pow => HirBinaryOpKind::Pow,
BinaryOpKind::BitAnd => HirBinaryOpKind::BitAnd,
BinaryOpKind::BitOr => HirBinaryOpKind::BitOr,
BinaryOpKind::BitXor => HirBinaryOpKind::BitXor,
BinaryOpKind::Shl => HirBinaryOpKind::Shl,
BinaryOpKind::Shr => HirBinaryOpKind::Shr,
}
}
fn lower_cond_operand(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
operand: CondOperand,
) -> HirExpr {
match operand {
CondOperand::Reg(reg) => expr_for_reg_use(lowering, block, instr_ref, reg),
CondOperand::Const(const_ref) => expr_for_const(lowering.proto, const_ref),
CondOperand::Nil => HirExpr::Nil,
CondOperand::Boolean(value) => HirExpr::Boolean(value),
CondOperand::Integer(value) => HirExpr::Integer(value),
CondOperand::Number(value) => HirExpr::Number(value.to_f64()),
}
}
fn lower_cond_operand_inline(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
operand: CondOperand,
) -> HirExpr {
match operand {
CondOperand::Reg(reg) => expr_for_reg_use_inline(lowering, block, instr_ref, reg),
CondOperand::Const(const_ref) => expr_for_const(lowering.proto, const_ref),
CondOperand::Nil => HirExpr::Nil,
CondOperand::Boolean(value) => HirExpr::Boolean(value),
CondOperand::Integer(value) => HirExpr::Integer(value),
CondOperand::Number(value) => HirExpr::Number(value.to_f64()),
}
}
fn lower_cond_operand_single_eval(
lowering: &ProtoLowering<'_>,
block: BlockRef,
instr_ref: InstrRef,
operand: CondOperand,
) -> HirExpr {
match operand {
CondOperand::Reg(reg) => expr_for_reg_use_single_eval(lowering, block, instr_ref, reg),
CondOperand::Const(const_ref) => expr_for_const(lowering.proto, const_ref),
CondOperand::Nil => HirExpr::Nil,
CondOperand::Boolean(value) => HirExpr::Boolean(value),
CondOperand::Integer(value) => HirExpr::Integer(value),
CondOperand::Number(value) => HirExpr::Number(value.to_f64()),
}
}