use crate::records::assign::Assign;
use crate::records::block::Block;
use crate::records::cfg_builder::CfgBuilder;
use crate::records::declare::Declare;
use crate::records::join::Join;
use crate::records::refine::Refine;
use crate::type_aliases::def_id_control_flow_graph::DefId;
use crate::type_aliases::instruction::{Instruction, InstructionMember};
use crate::type_aliases::refinement_control_flow_graph::Refinement;
use luaur_ast::records::ast_stat_assign::AstStatAssign;
use luaur_ast::records::ast_stat_local::AstStatLocal;
pub trait IntoInstruction<T> {
fn into_instruction(self) -> Instruction;
}
impl IntoInstruction<Declare> for (DefId, *mut AstStatLocal) {
fn into_instruction(self) -> Instruction {
Instruction::Declare(Declare::declare(self.0, self.1))
}
}
impl IntoInstruction<Assign> for (DefId, *mut AstStatAssign) {
fn into_instruction(self) -> Instruction {
Instruction::Assign(Assign::assign(self.0, self.1))
}
}
impl IntoInstruction<Join> for DefId {
fn into_instruction(self) -> Instruction {
Instruction::Join(Join {
definition: self,
operands: alloc::vec::Vec::new(),
})
}
}
impl IntoInstruction<Refine> for (DefId, *const Refinement) {
fn into_instruction(self) -> Instruction {
Instruction::Refine(Refine {
definition: self.0,
prop: self.1,
})
}
}
impl CfgBuilder {
pub fn emit<T, Args>(&mut self, block: *mut Block, args: Args) -> *mut T
where
Args: IntoInstruction<T>,
T: InstructionMember,
{
let allocator = unsafe { &mut *self.allocator };
let inst = allocator.new_instruction(args.into_instruction());
unsafe {
(*block).instructions.push(inst);
<T as InstructionMember>::get_if_mut(&mut *inst).unwrap() as *mut T
}
}
}