use crate::{
asm_generation::{convert_expression_to_asm, AsmNamespace, RegisterSequencer},
asm_lang::{ConstantRegister, Op, VirtualRegister},
error::*,
parse_tree::LazyOp,
semantic_analysis::TypedExpression,
CompileResult,
};
pub(crate) fn convert_lazy_operator_to_asm<'sc>(
op: &LazyOp,
lhs: &TypedExpression<'sc>,
rhs: &TypedExpression<'sc>,
return_register: &VirtualRegister,
namespace: &mut AsmNamespace<'sc>,
register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
let mut warnings = vec![];
let mut errors = vec![];
let mut asm_ops = vec![];
let mut lhs_asm_ops = check!(
convert_expression_to_asm(lhs, namespace, return_register, register_sequencer),
return err(warnings, errors),
warnings,
errors
);
asm_ops.append(&mut lhs_asm_ops);
let comparison_reg = match op {
LazyOp::And => ConstantRegister::One,
LazyOp::Or => ConstantRegister::Zero,
};
let skip_label = register_sequencer.get_label();
let mut jnei_op = Op::jump_if_not_equal(
return_register.clone(),
VirtualRegister::Constant(comparison_reg),
skip_label.clone(),
);
jnei_op.comment = "conditionally skip RHS for lazy operator".to_owned();
asm_ops.push(jnei_op);
let mut rhs_asm_ops = check!(
convert_expression_to_asm(rhs, namespace, return_register, register_sequencer),
return err(warnings, errors),
warnings,
errors
);
asm_ops.append(&mut rhs_asm_ops);
asm_ops.push(Op::unowned_jump_label(skip_label));
ok(asm_ops, warnings, errors)
}