use starlark_syntax::slice_vec_ext::SliceExt;
use crate::collections::symbol::symbol::Symbol;
use crate::eval::bc::compiler::expr::write_n_exprs;
use crate::eval::bc::instr_impl::InstrSetArrayIndex;
use crate::eval::bc::instr_impl::InstrSetObjectField;
use crate::eval::bc::instr_impl::InstrStoreModuleAndExport;
use crate::eval::bc::instr_impl::InstrUnpack;
use crate::eval::bc::stack_ptr::BcSlotIn;
use crate::eval::bc::stack_ptr::BcSlotOut;
use crate::eval::bc::writer::BcWriter;
use crate::eval::compiler::span::IrSpanned;
use crate::eval::compiler::stmt::AssignCompiledValue;
impl AssignCompiledValue {
pub(crate) fn mark_definitely_assigned_after(&self, bc: &mut BcWriter) {
match self {
AssignCompiledValue::Dot(object, field) => {
object.mark_definitely_assigned_after(bc);
let _ = field;
}
AssignCompiledValue::Module(..) => {}
AssignCompiledValue::Index(array, index) => {
array.mark_definitely_assigned_after(bc);
index.mark_definitely_assigned_after(bc);
}
AssignCompiledValue::LocalCaptured(_slot) => {}
AssignCompiledValue::Local(slot) => {
bc.mark_definitely_assigned(*slot);
}
AssignCompiledValue::Tuple(xs) => {
for x in xs {
x.mark_definitely_assigned_after(bc);
}
}
}
}
}
impl IrSpanned<AssignCompiledValue> {
pub(crate) fn write_bc(&self, value: BcSlotIn, bc: &mut BcWriter) {
let span = self.span;
match self.node {
AssignCompiledValue::Dot(ref object, ref field) => {
object.write_bc_cb(bc, |object, bc| {
let symbol = Symbol::new(field.as_str());
bc.write_instr::<InstrSetObjectField>(span, (value, object, symbol));
});
}
AssignCompiledValue::Index(ref array, ref index) => {
write_n_exprs([array, index], bc, |[array, index], bc| {
bc.write_instr::<InstrSetArrayIndex>(span, (value, array, index));
});
}
AssignCompiledValue::Tuple(ref xs) => {
let all_local = xs
.try_map(|x| {
x.as_local_non_captured()
.map(|l| l.to_bc_slot().to_out())
.ok_or(())
})
.ok();
if let Some(all_local) = all_local {
let args = bc.heap.alloc_any_slice(&all_local);
bc.write_instr::<InstrUnpack>(span, (value, args));
} else {
bc.alloc_slots(xs.len() as u32, |slots, bc| {
let args: Vec<BcSlotOut> = slots.iter().map(|s| s.to_out()).collect();
let args = bc.heap.alloc_any_slice(&args);
bc.write_instr::<InstrUnpack>(span, (value, args));
for (x, slot) in xs.iter().zip(slots.iter()) {
x.write_bc(slot.to_in(), bc);
}
});
}
}
AssignCompiledValue::Local(slot) => {
bc.write_mov(span, value, slot.to_bc_slot().to_out());
}
AssignCompiledValue::LocalCaptured(slot) => {
bc.write_store_local_captured(span, value, slot);
}
AssignCompiledValue::Module(slot, ref name) => {
bc.write_instr::<InstrStoreModuleAndExport>(span, (value, slot, name.clone()));
}
}
}
}