use super::{append_wgsl, emit_expr_string};
use crate::ir::model::expr::Expr;
use crate::ir::model::program::Program;
use crate::ir::model::types::AtomicOp;
use crate::lower::wgsl::{Error, LowerCtx};
pub(super) fn emit_atomic_expr(
out: &mut String,
op: AtomicOp,
buffer: &str,
index: &Expr,
expected: Option<&Expr>,
value: &Expr,
program: &Program,
ctx: &LowerCtx<'_>,
) -> Result<(), Error> {
if op != AtomicOp::CompareExchange && expected.is_some() {
return Err(Error::lowering(
"non-compare-exchange atomic includes an expected value. Fix: use Expr::Atomic.expected only with AtomicOp::CompareExchange.",
));
}
let fn_name = match &op {
AtomicOp::Add => "add",
AtomicOp::Or => "or",
AtomicOp::And => "and",
AtomicOp::Xor => "xor",
AtomicOp::Min => "min",
AtomicOp::Max => "max",
AtomicOp::Exchange => "exchange",
AtomicOp::CompareExchange => "compare_exchange",
};
append_wgsl(out, format_args!("_vyre_atomic_{fn_name}_{buffer}("))?;
emit_expr_string(out, index, program, ctx)?;
out.push_str(", ");
if op == AtomicOp::CompareExchange {
let expected = expected.ok_or_else(|| {
Error::lowering(
"compare-exchange atomic is missing expected value. Fix: set Expr::Atomic.expected for AtomicOp::CompareExchange.",
)
})?;
emit_expr_string(out, expected, program, ctx)?;
out.push_str(", ");
}
emit_expr_string(out, value, program, ctx)?;
out.push(')');
Ok(())
}