luaur-compiler 0.1.2

Luau source-to-bytecode compiler (Rust).
Documentation
use crate::records::compiler::Compiler;
use luaur_ast::records::ast_expr::AstExpr;
use luaur_ast::records::ast_expr_if_else::AstExprIfElse;
use luaur_ast::records::ast_node::AstNode;
use luaur_common::enums::luau_opcode::LuauOpcode;

impl Compiler {
    pub fn compile_expr_if_else(
        &mut self,
        expr: *mut AstExprIfElse,
        target: u8,
        target_temp: bool,
    ) {
        let expr_ref = unsafe { &*expr };

        if self.is_constant(expr_ref.condition) {
            if self.is_constant_true(expr_ref.condition) {
                self.compile_expr(expr_ref.true_expr, target, target_temp);
            } else {
                self.compile_expr(expr_ref.false_expr, target, target_temp);
            }
        } else {
            let creg = self.get_expr_local_reg(expr_ref.condition);
            if creg >= 0 {
                let true_reg = self.get_expr_local_reg(expr_ref.true_expr);
                let false_reg = self.get_expr_local_reg(expr_ref.false_expr);

                if creg == true_reg && (false_reg >= 0 || self.is_constant(expr_ref.false_expr)) {
                    return self.compile_expr_if_else_and_or(
                        false,
                        creg as u8,
                        expr_ref.false_expr,
                        target,
                    );
                } else if creg == false_reg
                    && (true_reg >= 0 || self.is_constant(expr_ref.true_expr))
                {
                    return self.compile_expr_if_else_and_or(
                        true,
                        creg as u8,
                        expr_ref.true_expr,
                        target,
                    );
                }
            }

            let mut else_jump = Vec::new();
            self.compile_condition_value(
                expr_ref.condition,
                core::ptr::null(),
                &mut else_jump,
                false,
            );
            self.compile_expr(expr_ref.true_expr, target, target_temp);

            let bytecode = unsafe { &mut *self.bytecode };
            let then_label = bytecode.emit_label();
            bytecode.emit_ad(LuauOpcode::LOP_JUMP, 0, 0);

            let else_label = bytecode.emit_label();
            self.compile_expr(expr_ref.false_expr, target, target_temp);
            let end_label = bytecode.emit_label();

            self.patch_jumps(expr as *mut AstNode, &mut else_jump, else_label);
            self.patch_jump(expr as *mut AstNode, then_label, end_label);
        }
    }
}