package org.jcnc.snow.compiler.ir.builder;

import org.jcnc.snow.compiler.ir.core.IROpCode;
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
import org.jcnc.snow.compiler.ir.instruction.ReturnInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;

/**
 * InstructionFactory 统一管理 IR 指令的创建，并自动将生成的指令添加到上下文中。
 *
 * <p>主要功能包括：
 * <ul>
 *   <li>生成加载常量指令（LoadConstInstruction）；</li>
 *   <li>生成二元运算指令（BinaryOperationInstruction）；</li>
 *   <li>生成返回指令（ReturnInstruction），支持有返回值和无返回值两种情况；</li>
 * </ul>
 */
public class InstructionFactory {

    /**
     * 生成加载整数常量的指令，并返回对应的结果寄存器。
     *
     * @param irContext 当前 IR 构建上下文
     * @param value 要加载的整数值
     * @return 存放常量的虚拟寄存器
     */
    public static IRVirtualRegister loadConst(IRContext irContext, int value) {
        IRVirtualRegister irVirtualRegister = irContext.newRegister();
        LoadConstInstruction instr = new LoadConstInstruction(irVirtualRegister, new IRConstant(value));
        irContext.addInstruction(instr);
        return irVirtualRegister;
    }

    /**
     * 生成二元运算指令，并返回运算结果寄存器。
     *
     * @param irContext 当前 IR 构建上下文
     * @param irOpCode  要执行的 IR 运算符
     * @param left  左操作数寄存器
     * @param right 右操作数寄存器
     * @return 存放运算结果的虚拟寄存器
     */
    public static IRVirtualRegister binOp(IRContext irContext, IROpCode irOpCode,
                                          IRVirtualRegister left,
                                          IRVirtualRegister right) {
        IRVirtualRegister dest = irContext.newRegister();
        BinaryOperationInstruction binaryOperationInstruction = new BinaryOperationInstruction(irOpCode, dest, left, right);
        irContext.addInstruction(binaryOperationInstruction);
        return dest;
    }

    /**
     * 生成带返回值的返回指令。
     *
     * @param irContext   当前 IR 构建上下文
     * @param value 需要返回的虚拟寄存器
     */
    public static void ret(IRContext irContext, IRVirtualRegister value) {
        irContext.addInstruction(new ReturnInstruction(value));
    }

    /**
     * 生成无返回值的返回指令。
     *
     * @param ctx 当前 IR 构建上下文
     */
    public static void retVoid(IRContext ctx) {
        ctx.addInstruction(new ReturnInstruction(null));
    }
}
